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

pengzheng pushed a commit to branch feature/clang-annotations
in repository https://gitbox.apache.org/repos/asf/celix.git

commit 245a3a2d4f0210cff3c450bd7d2eff42c93963ec
Author: PengZheng <[email protected]>
AuthorDate: Mon Nov 3 11:47:38 2025 +0800

    Add memory ownership annotations and improve documentation clarity. 
Standardize function declarations with explicit `void` parameters for 
consistency.
---
 libs/utils/gtest/src/PropertiesTestSuite.cc    |   4 +-
 libs/utils/include/celix_array_list.h          | 219 +++++++++++++------------
 libs/utils/include/celix_array_list_encoding.h |  22 +--
 libs/utils/include/celix_cleanup.h             |   4 +-
 libs/utils/include/celix_compiler.h            |  76 +++++++++
 libs/utils/include/celix_convert_utils.h       |  37 ++---
 libs/utils/include/celix_filter.h              |  76 +++++----
 libs/utils/include/celix_long_hash_map.h       |  57 ++++---
 libs/utils/include/celix_properties.h          | 165 ++++++++++---------
 libs/utils/include/celix_string_hash_map.h     |  74 +++++----
 libs/utils/include/celix_utils.h               |  81 +++++----
 libs/utils/include/celix_version.h             |  49 ++++--
 libs/utils/include/celix_version_range.h       |  42 +++--
 libs/utils/src/array_list.c                    |  14 +-
 libs/utils/src/celix_hash_map.c                |   4 +-
 libs/utils/src/properties.c                    |   2 +-
 libs/utils/src/version.c                       |   2 +-
 libs/utils/src/version_range.c                 |   2 +-
 18 files changed, 541 insertions(+), 389 deletions(-)

diff --git a/libs/utils/gtest/src/PropertiesTestSuite.cc 
b/libs/utils/gtest/src/PropertiesTestSuite.cc
index bfb908783..5829137db 100644
--- a/libs/utils/gtest/src/PropertiesTestSuite.cc
+++ b/libs/utils/gtest/src/PropertiesTestSuite.cc
@@ -33,7 +33,7 @@ class PropertiesTestSuite : public ::testing::Test {
   public:
     PropertiesTestSuite() { celix_err_resetErrors(); }
 
-    void printStats(const celix_properties_statistics_t* stats) {
+    static void printStats(const celix_properties_statistics_t* stats) {
         printf("Properties statistics:\n");
         printf("|- nr of entries: %zu\n", stats->mapStatistics.nrOfEntries);
         printf("|- nr of buckets: %zu\n", stats->mapStatistics.nrOfBuckets);
@@ -951,4 +951,4 @@ TEST_F(PropertiesTestSuite, EmptyStringKeyTest) {
     celix_properties_set(props, "", "value"); // "" is a valid key (nullptr is 
not)
     EXPECT_EQ(1, celix_properties_size(props));
     EXPECT_STREQ("value", celix_properties_getString(props, ""));
-}
+}
\ No newline at end of file
diff --git a/libs/utils/include/celix_array_list.h 
b/libs/utils/include/celix_array_list.h
index 8393bc238..a4178bae0 100644
--- a/libs/utils/include/celix_array_list.h
+++ b/libs/utils/include/celix_array_list.h
@@ -17,17 +17,18 @@
  * under the License.
  */
 
+#ifndef CELIX_ARRAY_LIST_H_
+#define CELIX_ARRAY_LIST_H_
+
 #include <stdbool.h>
 
 #include "celix_array_list_type.h"
 #include "celix_utils_export.h"
 #include "celix_cleanup.h"
+#include "celix_compiler.h"
 #include "celix_errno.h"
 #include "celix_version_type.h"
 
-#ifndef CELIX_ARRAY_LIST_H_
-#define CELIX_ARRAY_LIST_H_
-
 /**
  * Init macro so that the opts are correctly initialized for C++ compilers
  */
@@ -72,7 +73,7 @@ typedef union celix_array_list_entry {
     void* voidPtrVal;      /**< A pointer value when the element type is 
CELIX_ARRAY_LIST_ELEMENT_TYPE_PTR or
                               CELIX_ARRAY_LIST_ELEMENT_TYPE_UNDEFINED. */
     const char* stringVal; /**< A string value when the element type is 
CELIX_ARRAY_LIST_ELEMENT_TYPE_STRING,
-                              CELIX_ARRAY_LIST_ELEMENT_TYPE_STRING_REF or 
CELIX_ARRAY_LIST_ELEMENT_TYPE_UNDEFINED. */
+                              CELIX_ARRAY_LIST_ELEMENT_TYPE_STRING_REF, or 
CELIX_ARRAY_LIST_ELEMENT_TYPE_UNDEFINED. */
     long int longVal;      /**< A long integer value when the element type is 
CELIX_ARRAY_LIST_ELEMENT_TYPE_LONG or
                               CELIX_ARRAY_LIST_ELEMENT_TYPE_UNDEFINED. */
     double doubleVal;       /**< A double value when the element type is 
CELIX_ARRAY_LIST_ELEMENT_TYPE_DOUBLE or
@@ -84,17 +85,17 @@ typedef union celix_array_list_entry {
 } celix_array_list_entry_t;
 
 /**
- * @brief Equals function for array list entries, can be provided when 
creating a array list.
+ * @brief Equals function for array list entries can be provided when creating 
an array list.
  */
 typedef bool (*celix_arrayList_equals_fp)(celix_array_list_entry_t, 
celix_array_list_entry_t);
 
 /**
- * @brief Compare function for array list entries, which can be used to sort a 
array list.
+ * @brief Compare function for array list entries, which can be used to sort 
an array list.
  */
 typedef int (*celix_array_list_compare_entries_fp)(celix_array_list_entry_t a, 
celix_array_list_entry_t b);
 
 /**
- * @brief Copy function for array list entries, which can be used to copy a 
array list entry.
+ * @brief Copy function for array list entries, which can be used to copy an 
array list entry.
  * @return CELIX_SUCCESS if the entry is copied, CELIX_ENOMEM if the entry 
could not be copied.
  */
 typedef celix_status_t 
(*celix_array_list_copy_entry_fp)(celix_array_list_entry_t src, 
celix_array_list_entry_t* dst);
@@ -103,102 +104,109 @@ typedef celix_status_t 
(*celix_array_list_copy_entry_fp)(celix_array_list_entry_
  * @brief Creates a new empty array list with an undefined element type.
  * @deprecated Use celix_arrayList_createWithOptions or 
celix_arrayList_create<Type>Array instead.
  *
- * The remove, equals and compare callback will be NULL.
+ * The remove, equals, and compare callback will be NULL.
  *
- * @return A new empty array list or NULL if the array list could not be 
created. If NULL is returned an error message
+ * @return A new empty array list or NULL if the array list could not be 
created. If NULL is returned, an error message
  * is logged to celix_err.
  */
 CELIX_UTILS_DEPRECATED_EXPORT
-celix_array_list_t* celix_arrayList_create();
+CELIX_OWNERSHIP_RETURNS(celix_array_list)
+celix_array_list_t* celix_arrayList_create(void);
 
 /**
  * @brief Creates a new empty array list with a pointer element type where the 
array list is not the owner of the
  * pointers.
  *
- * The remove, equals, compare and copy callback will be NULL.
+ * The remove, equals, compare, and copy callback will be NULL.
  *
- * @return A new empty array list or NULL if the array list could not be 
created. If NULL is returned an error message
+ * @return A new empty array list or NULL if the array list could not be 
created. If NULL is returned, an error message
  * is logged to celix_err.
  */
 CELIX_UTILS_EXPORT
-celix_array_list_t* celix_arrayList_createPointerArray();
+CELIX_OWNERSHIP_RETURNS(celix_array_list)
+celix_array_list_t* celix_arrayList_createPointerArray(void);
 
 /**
  * @brief Creates a new empty array list with a string element type where the 
array list is the owner of the strings.
  *
  * The remove callback will be configured to free the string, the equals and 
compare callback will be configured for
- * string comparison and the copy callback will be a callback to uses 
celix_utils_strdup.
+ * string comparison, and the copy callback will be a callback to use 
celix_utils_strdup.
  *
- * @return A new empty array list or NULL if the array list could not be 
created. If NULL is returned an error message
+ * @return A new empty array list or NULL if the array list could not be 
created. If NULL is returned, an error message
  * is logged to celix_err.
  */
 CELIX_UTILS_EXPORT
-celix_array_list_t* celix_arrayList_createStringArray();
+CELIX_OWNERSHIP_RETURNS(celix_array_list)
+celix_array_list_t* celix_arrayList_createStringArray(void);
 
 /**
  * @brief Creates a new empty array list with a long integer element type.
  *
  * The remove callback will be configured to NULL, the equals and compare 
callback will be configured for
- * integer comparison and the copy callback will be configured to NULL.
+ * integer comparison, and the copy callback will be configured to NULL.
  *
- * @return A new empty array list or NULL if the array list could not be 
created. If NULL is returned an error message
+ * @return A new empty array list or NULL if the array list could not be 
created. If NULL is returned, an error message
  * is logged to celix_err.
  */
 CELIX_UTILS_EXPORT
-celix_array_list_t* celix_arrayList_createLongArray();
+CELIX_OWNERSHIP_RETURNS(celix_array_list)
+celix_array_list_t* celix_arrayList_createLongArray(void);
 
 /**
  * @brief Creates a new empty array list with a double element type.
  *
  * The remove callback will be configured to NULL, the equals and compare 
callback will be configured for
- * double comparison and the copy callback will be configured to NULL.
+ * double comparison, and the copy callback will be configured to NULL.
  *
- * @return A new empty array list or NULL if the array list could not be 
created. If NULL is returned an error message
+ * @return A new empty array list or NULL if the array list could not be 
created. If NULL is returned, an error message
  * is logged to celix_err.
  */
 CELIX_UTILS_EXPORT
-celix_array_list_t* celix_arrayList_createDoubleArray();
+CELIX_OWNERSHIP_RETURNS(celix_array_list)
+celix_array_list_t* celix_arrayList_createDoubleArray(void);
 
 /**
  * @brief Creates a new empty array list with a boolean element type.
  *
  * The remove callback will be configured to NULL, the equals and compare 
callback will be configured for
- * boolean comparison and the copy callback will be configured to NULL.
+ * boolean comparison, and the copy callback will be configured to NULL.
  *
- * @return A new empty array list or NULL if the array list could not be 
created. If NULL is returned an error message
+ * @return A new empty array list or NULL if the array list could not be 
created. If NULL is returned, an error message
  * is logged to celix_err.
  */
 CELIX_UTILS_EXPORT
-celix_array_list_t* celix_arrayList_createBoolArray();
+CELIX_OWNERSHIP_RETURNS(celix_array_list)
+celix_array_list_t* celix_arrayList_createBoolArray(void);
 
 /**
  * @brief Creates a new empty array list with a celix_version_t* element type.
  *
  * The remove callback will be configured to free a celix version, the equals 
and compare callback will be configured
- * for celix version comparison and the copy callback will a callback that 
uses celix_version_copy.
+ * for celix version comparison, and the copy callback will be a callback that 
uses celix_version_copy.
  *
- * @return A new empty array list or NULL if the array list could not be 
created. If NULL is returned an error message
+ * @return A new empty array list or NULL if the array list could not be 
created. If NULL is returned, an error message
  * is logged to celix_err.
  */
 CELIX_UTILS_EXPORT
-celix_array_list_t* celix_arrayList_createVersionArray();
+CELIX_OWNERSHIP_RETURNS(celix_array_list)
+celix_array_list_t* celix_arrayList_createVersionArray(void);
 
 /**
- * Additional create options when creating a array list.
+ * Additional creation options when creating an array list.
  */
 typedef struct celix_array_list_create_options {
     /**
-     * The element type of the array list. Default is 
CELIX_ARRAY_LIST_ELEMENT_TYPE_UNDEFINED.
+     * The element type of the array list. The default is 
CELIX_ARRAY_LIST_ELEMENT_TYPE_UNDEFINED.
      */
     celix_array_list_element_type_t elementType CELIX_OPTS_INIT;
 
     /**
-     * A simple removed callback, which if provided will be called if a entry 
is removed
-     * from the array list. The removed entry is provided as pointer.
+     * A simple removed callback. If provided, it will be called if an entry 
is removed
+     * from the array list. The removed entry is provided as a pointer.
      *
      * @note Assumes that the array list entries are pointer values.
      *
-     * @note only simpleRemovedCallback or removedCallback should be 
configured, if both are configured,
+     * @note Only simpleRemovedCallback or removedCallback should be 
configured, if both are configured,
      * only the simpledRemoveCallback will be used.
      *
      * Default is NULL.
@@ -213,10 +221,10 @@ typedef struct celix_array_list_create_options {
     void* removedCallbackData CELIX_OPTS_INIT;
 
     /**
-     * A removed callback, which if provided will be called if a entry is 
removed from the array list.
-     * The callback data pointer will be provided as first argument to the 
removed callback.
+     * A removed callback. If provided, it will be called if an entry is 
removed from the array list.
+     * The callback data pointer will be provided as the first argument to the 
removed callback.
      *
-     * @note only simpleRemovedCallback or removedCallback should be 
configured, if both are configured,
+     * @note Only simpleRemovedCallback or removedCallback should be 
configured, if both are configured,
      * only the simpledRemoveCallback will be used.
      *
      * Default is NULL.
@@ -224,7 +232,7 @@ typedef struct celix_array_list_create_options {
     void (*removedCallback)(void* data, celix_array_list_entry_t entry) 
CELIX_OPTS_INIT;
 
     /**
-     * Equals callback used when trying to find a array list entry.
+     * Equals callback used when trying to find an array list entry.
      */
     celix_arrayList_equals_fp equalsCallback CELIX_OPTS_INIT;
 
@@ -234,8 +242,8 @@ typedef struct celix_array_list_create_options {
     celix_array_list_compare_entries_fp compareCallback CELIX_OPTS_INIT;
 
     /**
-     * The copy callback used to copy a array list entry.
-     * If callback is NULL, a celix_arrayList_copy will result in a shallow 
copy.
+     * The copy callback used to copy an array list entry.
+     * If the callback is NULL, a celix_arrayList_copy will result in a 
shallow copy.
      */
     celix_array_list_copy_entry_fp copyCallback CELIX_OPTS_INIT;
 
@@ -248,7 +256,7 @@ typedef struct celix_array_list_create_options {
 
 #ifndef __cplusplus
 /**
- * @brief C Macro to create a empty celix_array_list_create_options_t type.
+ * @brief C Macro to create an empty celix_array_list_create_options_t type.
  */
 #define CELIX_EMPTY_ARRAY_LIST_CREATE_OPTIONS                                  
                                        \
     {                                                                          
                                        \
@@ -259,19 +267,20 @@ typedef struct celix_array_list_create_options {
 #endif
 
 /**
- * @brief Creates a new empty array list using using the provided array list 
create options.
+ * @brief Creates a new empty array list using the provided array list create 
options.
  *
  * The callbacks in the options will override the default callbacks based on 
the provided element type.
- * The default callbacks (e.g. the remove, equals, compare and copy callback) 
correspond to the
+ * The default callbacks (e.g., the remove, equals, compare, and copy 
callback) correspond to the
  * celix_arrayList_create<Type>Array function.
- * For example if the elementType is CELIX_ARRAY_LIST_ELEMENT_TYPE_STRING, the 
default callbacks will be set to
+ * For example, if the elementType is CELIX_ARRAY_LIST_ELEMENT_TYPE_STRING, 
the default callbacks will be set to
  * handle string values.
  *
  * @param opts The create options, only used during the creation of the array 
list.
- * @return A new empty array list or NULL if the array list could not be 
created. If NULL is returned an error message
+ * @return A new empty array list or NULL if the array list could not be 
created. If NULL is returned, an error message
  * is logged to celix_err.
  */
 CELIX_UTILS_EXPORT
+CELIX_OWNERSHIP_RETURNS(celix_array_list)
 celix_array_list_t* celix_arrayList_createWithOptions(const 
celix_array_list_create_options_t* opts);
 
 /**
@@ -280,6 +289,7 @@ celix_array_list_t* celix_arrayList_createWithOptions(const 
celix_array_list_cre
  * @note If a (simple) removed callback is configured, the callback will be 
called for every array list entry.
  */
 CELIX_UTILS_EXPORT
+CELIX_OWNERSHIP_TAKES(celix_array_list, 1)
 void celix_arrayList_destroy(celix_array_list_t *list);
 
 CELIX_DEFINE_AUTOPTR_CLEANUP_FUNC(celix_array_list_t, celix_arrayList_destroy)
@@ -299,12 +309,12 @@ int celix_arrayList_size(const celix_array_list_t *list);
 /**
  * @brief Returns the value for the provided index.
  *
- * Can be used for array list with element type 
CELIX_ARRAY_LIST_ELEMENT_TYPE_POINTER or
+ * Can be used for an array list with element type 
CELIX_ARRAY_LIST_ELEMENT_TYPE_POINTER or
  * CELIX_ARRAY_LIST_ELEMENT_TYPE_UNDEFINED.
  *
  * @param list The array list.
  * @param index The entry index to return.
- * @return Returns the pointer value for the index. Returns NULL if index is 
out of bound.
+ * @return Returns the pointer value for the index. Returns NULL if the index 
is out of bound.
  */
 CELIX_UTILS_EXPORT
 void* celix_arrayList_get(const celix_array_list_t *list, int index);
@@ -312,12 +322,12 @@ void* celix_arrayList_get(const celix_array_list_t *list, 
int index);
 /**
  * @brief Returns the value for the provided index.
  *
- * Can be used for array list with element type 
CELIX_ARRAY_LIST_ELEMENT_TYPE_STRING
+ * Can be used for an array list with element type 
CELIX_ARRAY_LIST_ELEMENT_TYPE_STRING
  * or CELIX_ARRAY_LIST_ELEMENT_TYPE_UNDEFINED.
  *
  * @param list The array list.
  * @param index The entry index to return.
- * @return Returns the string value for the index. Returns NULL if index is 
out of bound.
+ * @return Returns the string value for the index. Returns NULL if the index 
is out of bound.
  */
 CELIX_UTILS_EXPORT
 const char* celix_arrayList_getString(const celix_array_list_t *list, int 
index);
@@ -325,12 +335,12 @@ const char* celix_arrayList_getString(const 
celix_array_list_t *list, int index)
 /**
  * @brief Returns the value for the provided index.
  *
- * Can be used for array list with element type 
CELIX_ARRAY_LIST_ELEMENT_TYPE_LONG or
+ * Can be used for an array list with element type 
CELIX_ARRAY_LIST_ELEMENT_TYPE_LONG or
  * CELIX_ARRAY_LIST_ELEMENT_TYPE_UNDEFINED.
  *
  * @param list The array list.
  * @param index The entry index to return.
- * @return Returns the long value for the index. Returns 0 if index is out of 
bound.
+ * @return Returns the long value for the index. Returns 0 if the index is out 
of bound.
  */
 CELIX_UTILS_EXPORT
 long int celix_arrayList_getLong(const celix_array_list_t *list, int index);
@@ -338,12 +348,12 @@ long int celix_arrayList_getLong(const celix_array_list_t 
*list, int index);
 /**
  * @brief Returns the value for the provided index.
  *
- * Can be used for array list with element type 
CELIX_ARRAY_LIST_ELEMENT_TYPE_DOUBLE or
+ * Can be used for an array list with element type 
CELIX_ARRAY_LIST_ELEMENT_TYPE_DOUBLE or
  * CELIX_ARRAY_LIST_ELEMENT_TYPE_UNDEFINED.
  *
  * @param list The array list.
  * @param index The entry index to return.
- * @return Returns the double value for the index. Returns 0 if index is out 
of bound.
+ * @return Returns the double value for the index. Returns 0 if the index is 
out of bound.
  */
 CELIX_UTILS_EXPORT
 double celix_arrayList_getDouble(const celix_array_list_t *list, int index);
@@ -351,12 +361,12 @@ double celix_arrayList_getDouble(const celix_array_list_t 
*list, int index);
 /**
  * @brief Returns the value for the provided index.
  *
- * Can be used for array list with element type 
CELIX_ARRAY_LIST_ELEMENT_TYPE_BOOL or
+ * Can be used for an array list with element type 
CELIX_ARRAY_LIST_ELEMENT_TYPE_BOOL or
  * CELIX_ARRAY_LIST_ELEMENT_TYPE_UNDEFINED.
  *
  * @param list The array list.
  * @param index The entry index to return.
- * @return Returns the bool value for the index. Returns false if index is out 
of bound.
+ * @return Returns the bool value for the index. Returns false if the index is 
out of bound.
  */
 CELIX_UTILS_EXPORT
 bool celix_arrayList_getBool(const celix_array_list_t *list, int index);
@@ -364,12 +374,12 @@ bool celix_arrayList_getBool(const celix_array_list_t 
*list, int index);
 /**
  * @brief Returns the value for the provided index.
  *
- * Can be used for array list with element type 
CELIX_ARRAY_LIST_ELEMENT_TYPE_VERSION,
+ * Can be used for an array list with element type 
CELIX_ARRAY_LIST_ELEMENT_TYPE_VERSION,
  * or CELIX_ARRAY_LIST_ELEMENT_TYPE_UNDEFINED.
  *
  * @param list The array list.
  * @param index The entry index to return.
- * @return Returns the version value for the index. Returns NULL if index is 
out of bound.
+ * @return Returns the version value for the index. Returns NULL if the index 
is out of bound.
  */
 CELIX_UTILS_EXPORT
 const celix_version_t* celix_arrayList_getVersion(const celix_array_list_t 
*list, int index);
@@ -379,15 +389,15 @@ const celix_version_t* celix_arrayList_getVersion(const 
celix_array_list_t *list
  *
  * @param list The array list.
  * @param index The entry index to return.
- * @return Returns the entry for the index. Returns NULL if index is out of 
bound.
+ * @return Returns the entry for the index. Returns NULL if the index is out 
of bound.
  */
 CELIX_UTILS_EXPORT
 celix_array_list_entry_t celix_arrayList_getEntry(const celix_array_list_t 
*list, int index);
 
 /**
- * @brief add pointer entry to the back of the array list.
+ * @brief Add a pointer entry to the back of the array list.
  *
- * Can be used for array list with element type 
CELIX_ARRAY_LIST_ELEMENT_TYPE_POINTER or
+ * Can be used for an array list with element type 
CELIX_ARRAY_LIST_ELEMENT_TYPE_POINTER or
  * CELIX_ARRAY_LIST_ELEMENT_TYPE_UNDEFINED.
  *
  * If the return status is an error, an error message is logged to celix_err.
@@ -402,7 +412,7 @@ celix_status_t celix_arrayList_add(celix_array_list_t* 
list, void* value);
 /**
  * @brief Add a string entry to the back of the array list.
  *
- * Can be used for array list with element type 
CELIX_ARRAY_LIST_ELEMENT_TYPE_STRING
+ * Can be used for an array list with element type 
CELIX_ARRAY_LIST_ELEMENT_TYPE_STRING
  * or CELIX_ARRAY_LIST_ELEMENT_TYPE_UNDEFINED.
  *
  * If the array list element type is CELIX_ARRAY_LIST_ELEMENT_TYPE_STRING, the 
string will be copied, but
@@ -421,24 +431,25 @@ celix_status_t 
celix_arrayList_addString(celix_array_list_t* list, const char* v
 /**
  * @brief Add a string entry to the back of a string array list.
  *
- * The string will not be copied and the array list will take ownership of the 
string.
+ * The string will not be copied, and the array list will take ownership of 
the string.
  *
- * Can only be used for array list with element type 
CELIX_ARRAY_LIST_ELEMENT_TYPE_STRING.
+ * Can only be used for an array list of element type 
CELIX_ARRAY_LIST_ELEMENT_TYPE_STRING.
  *
  * If the return status is an error, an error message is logged to celix_err.
  *
  * @param list The array list.
  * @param value The string value to add to the array list. Cannot be NULL.
- * @return CELIX_SUCCESS if the value is added, CELIX_ENOMEM if the array list 
is out of memory. If an error is returned
+ * @return CELIX_SUCCESS if the value is added, CELIX_ENOMEM if the array list 
is out of memory. If an error is returned,
  * the provided value is not added to the array list, but the value will be 
freed using free.
  */
 CELIX_UTILS_EXPORT
+CELIX_OWNERSHIP_HOLDS(malloc, 2)
 celix_status_t celix_arrayList_assignString(celix_array_list_t* list, char* 
value);
 
 /**
  * @brief add pointer entry to the back of the array list.
  *
- * Can be used for array list with element type 
CELIX_ARRAY_LIST_ELEMENT_TYPE_LONG or
+ * Can be used for an array list with element type 
CELIX_ARRAY_LIST_ELEMENT_TYPE_LONG or
  * CELIX_ARRAY_LIST_ELEMENT_TYPE_UNDEFINED.
  *
  * If the return status is an error, an error message is logged to celix_err.
@@ -453,7 +464,7 @@ celix_status_t celix_arrayList_addLong(celix_array_list_t* 
list, long value);
 /**
  * @brief add pointer entry to the back of the array list.
  *
- * Can be used for array list with element type 
CELIX_ARRAY_LIST_ELEMENT_TYPE_DOUBLE or
+ * Can be used for an array list with element type 
CELIX_ARRAY_LIST_ELEMENT_TYPE_DOUBLE or
  * CELIX_ARRAY_LIST_ELEMENT_TYPE_UNDEFINED.
  *
  * If the return status is an error, an error message is logged to celix_err.
@@ -468,7 +479,7 @@ celix_status_t 
celix_arrayList_addDouble(celix_array_list_t* list, double value)
 /**
  * @brief add pointer entry to the back of the array list.
  *
- * Can be used for array list with element type 
CELIX_ARRAY_LIST_ELEMENT_TYPE_BOOL or
+ * Can be used for an array list with element type 
CELIX_ARRAY_LIST_ELEMENT_TYPE_BOOL or
  * CELIX_ARRAY_LIST_ELEMENT_TYPE_UNDEFINED.
  *
  * If the return status is an error, an error message is logged to celix_err.
@@ -483,7 +494,7 @@ celix_status_t celix_arrayList_addBool(celix_array_list_t* 
list, bool value);
 /**
  * @brief Add a version entry to the back of the version array list.
  *
- * Can be used for array list with element type 
CELIX_ARRAY_LIST_ELEMENT_TYPE_VERSION,
+ * Can be used for an array list with element type 
CELIX_ARRAY_LIST_ELEMENT_TYPE_VERSION
  * or CELIX_ARRAY_LIST_ELEMENT_TYPE_UNDEFINED.
  *
  * If the array list element type is CELIX_ARRAY_LIST_ELEMENT_TYPE_VERSION, 
the version will be copied, but
@@ -502,8 +513,8 @@ celix_status_t 
celix_arrayList_addVersion(celix_array_list_t* list, const celix_
 /**
  * @brief Add a version entry to the back of a version array list.
  *
- * Can be used for array list with element type 
CELIX_ARRAY_LIST_ELEMENT_TYPE_VERSION.
- * The version will not be copied and the array list will take ownership of 
the version.
+ * Can be used for an array list of element type 
CELIX_ARRAY_LIST_ELEMENT_TYPE_VERSION.
+ * The version will not be copied, and the array list will take ownership of 
the version.
  *
  * If the return status is an error, an error message is logged to celix_err.
  *
@@ -513,16 +524,17 @@ celix_status_t 
celix_arrayList_addVersion(celix_array_list_t* list, const celix_
  * returned, the provided value is not added to the array list, but the value 
will be freed using celix_version_destroy.
  */
 CELIX_UTILS_EXPORT
+CELIX_OWNERSHIP_HOLDS(celix_version, 2)
 celix_status_t celix_arrayList_assignVersion(celix_array_list_t* list, 
celix_version_t* value);
 
 /**
  * @brief Returns the index of the provided entry, if found.
  *
  * The equals callback function provided when the array list was created will 
be used
- * to determine if a array list entry equals the provided entry.
+ * to determine if an array list entry equals the provided entry.
  *
  * The equals callback provided when the array list was created will be used 
to find the entry.
- * If there was no equals callback provided a direct memory compare will be 
done.
+ * If there was no equals callback provided, a direct memory compare will be 
done.
  *
  * @param list The array list.
  * @param entry The entry to find.
@@ -547,85 +559,85 @@ CELIX_UTILS_EXPORT
 void celix_arrayList_clear(celix_array_list_t *list);
 
 /**
- * @brief Remove the first entry from array list which matches the provided 
value.
+ * @brief Remove the first entry, which matches the provided value, from the 
given array list.
  *
  * The provided entry is expected to be cleared using memset, before it gets 
assigned a value.
- * If there is no equals provided, the entry will not be removed.
+ * If there is no equals callback provided, the entry will not be removed.
  *
  * The equals callback provided when the array list was created will be used 
to find the entry.
- * If there was no equals callback provided a direct memory compare will be 
done.
+ * If there was no equals callback provided, a direct memory compare will be 
done.
  */
 CELIX_UTILS_EXPORT
 void celix_arrayList_removeEntry(celix_array_list_t *list, 
celix_array_list_entry_t entry);
 
 /**
- * @brief Remove the first pointer entry from array list which matches the 
provided value.
+ * @brief Remove the first pointer entry, which matches the provided value, 
from the given array list.
  *
- * Can be used for array list with element type 
CELIX_ARRAY_LIST_ELEMENT_TYPE_POINTER or
+ * Can be used for an array list of element type 
CELIX_ARRAY_LIST_ELEMENT_TYPE_POINTER or
  * CELIX_ARRAY_LIST_ELEMENT_TYPE_UNDEFINED.
  *
  * The equals callback provided when the array list was created will be used 
to find the entry.
- * If there was no equals callback provided a direct memory compare will be 
done.
+ * If there was no equals callback provided, a direct memory compare will be 
done.
  */
 CELIX_UTILS_EXPORT
 void celix_arrayList_remove(celix_array_list_t* list, void* value);
 
 /**
- * @brief Remove the first string entry from array list which matches the 
provided value.
+ * @brief Remove the first string entry, which matches the provided value, 
from the given array list.
  *
- * Can be used for array list with element type 
CELIX_ARRAY_LIST_ELEMENT_TYPE_STRING and
+ * Can be used for an array list with element type 
CELIX_ARRAY_LIST_ELEMENT_TYPE_STRING and
  * CELIX_ARRAY_LIST_ELEMENT_TYPE_UNDEFINED.
  *
  * The equals callback provided when the array list was created will be used 
to find the entry.
- * If there was no equals callback provided a direct memory compare will be 
done.
+ * If there was no equals callback provided, a direct memory compare will be 
done.
  */
 CELIX_UTILS_EXPORT
 void celix_arrayList_removeString(celix_array_list_t* list, const char* value);
 
 /**
- * @brief Remove the first long entry from array list which matches the 
provided value.
+ * @brief Remove the first long entry, which matches the provided value, from 
the given array list.
  *
- * Can be used for array list with element type 
CELIX_ARRAY_LIST_ELEMENT_TYPE_LONG and
+ * Can be used for an array list with element type 
CELIX_ARRAY_LIST_ELEMENT_TYPE_LONG and
  * CELIX_ARRAY_LIST_ELEMENT_TYPE_UNDEFINED.
  *
  * The equals callback provided when the array list was created will be used 
to find the entry.
- * If there was no equals callback provided a direct memory compare will be 
done.
+ * If there was no equals callback provided, a direct memory compare will be 
done.
  */
 CELIX_UTILS_EXPORT
 void celix_arrayList_removeLong(celix_array_list_t* list, long value);
 
 /**
- * @brief Remove the first double entry from array list which matches the 
provided value.
+ * @brief Remove the first double entry, which matches the provided value, 
from the given array list.
  *
- * Can be used for array list with element type 
CELIX_ARRAY_LIST_ELEMENT_TYPE_DOUBLE and
+ * Can be used for an array list of element type 
CELIX_ARRAY_LIST_ELEMENT_TYPE_DOUBLE and
  * CELIX_ARRAY_LIST_ELEMENT_TYPE_UNDEFINED.
  *
  * The equals callback provided when the array list was created will be used 
to find the entry.
- * If there was no equals callback provided a direct memory compare will be 
done.
+ * If there was no equals callback provided, a direct memory compare will be 
done.
  */
 CELIX_UTILS_EXPORT
 void celix_arrayList_removeDouble(celix_array_list_t* list, double value);
 
 /**
- * @brief Remove the first bool entry from array list which matches the 
provided value.
+ * @brief Remove the first bool entry, which matches the provided value, from 
the given array list.
  *
- * Can be used for array list with element type 
CELIX_ARRAY_LIST_ELEMENT_TYPE_BOOL and
+ * Can be used for an array list of element type 
CELIX_ARRAY_LIST_ELEMENT_TYPE_BOOL and
  * CELIX_ARRAY_LIST_ELEMENT_TYPE_UNDEFINED.
  *
  * The equals callback provided when the array list was created will be used 
to find the entry.
- * If there was no equals callback provided a direct memory compare will be 
done.
+ * If there was no equals callback provided, a direct memory compare will be 
done.
  */
 CELIX_UTILS_EXPORT
 void celix_arrayList_removeBool(celix_array_list_t* list, bool value);
 
 /**
- * @brief Remove the first version entry from array list which matches the 
provided value.
+ * @brief Remove the first version entry, which matches the provided value, 
from the given array list.
  *
- * Can be used for array list with element type 
CELIX_ARRAY_LIST_ELEMENT_TYPE_VERSION and
+ * Can be used for an array list of element type 
CELIX_ARRAY_LIST_ELEMENT_TYPE_VERSION and
  * CELIX_ARRAY_LIST_ELEMENT_TYPE_UNDEFINED.
  *
  * The equals callback provided when the array list was created will be used 
to find the entry.
- * If there was no equals callback provided a direct memory compare will be 
done.
+ * If there was no equals callback provided, a direct memory compare will be 
done.
  */
 CELIX_UTILS_EXPORT
 void celix_arrayList_removeVersion(celix_array_list_t* list, const 
celix_version_t* value);
@@ -638,27 +650,27 @@ void celix_arrayList_sortEntries(celix_array_list_t 
*list, celix_array_list_comp
 
 /**
  * @brief Sort the array list using the array list configured compare function.
- * Note that undefined the array list compare function can be NULL and in that 
case the array list will not be sorted.
+ * Note that undefined the array list compare function can be NULL, and in 
that case the array list will not be sorted.
  */
 CELIX_UTILS_EXPORT
 void celix_arrayList_sort(celix_array_list_t *list);
 
 /**
- * @brief Check if the array list are equal.
+ * @brief Check if the array list is equal.
  *
  * Equal is defined as:
- * - The array list have the same size
- * - The array list have the same element type
- * - The array list have the same equals callback
- * - The array list have the same values at the same index
+ * - The array list has the same size
+ * - The array list has the same element type
+ * - The array list has the same equals callback
+ * - The array list has the same values at the same index
  *
- * Note that the remove, compare and copy callbacks are ignored.
+ * Notes that the remove, compare, and copy callbacks are ignored.
  *
- * If both array list are NULL, they are considered equal.
+ * If both array lists are NULL, they are considered equal.
  *
  * @param listA The first array list.
  * @param listB The second array list.
- * @return true if the array list are equal, false otherwise.
+ * @return true if the array lists are equal, false otherwise.
  */
 CELIX_UTILS_EXPORT
 bool celix_arrayList_equals(const celix_array_list_t* listA, const 
celix_array_list_t* listB);
@@ -667,16 +679,17 @@ bool celix_arrayList_equals(const celix_array_list_t* 
listA, const celix_array_l
  * @Brief Copy the array list to a new array list.
  *
  * The new array list will have the same element type and the same callbacks 
as the original array list.
- * For copying the array list entries the copy callback will be used, if the 
capy callback is NULL a shallow copy will
+ * For copying the array list entries, the copy callback will be used, if the 
capy callback is NULL, a shallow copy will
  * be done.
  *
- * If a NULL is returned and the original array list is not NULL, a error 
message is logged to celix_err.
+ * If a NULL is returned and the original array list is not NULL, an error 
message is logged to celix_err.
  *
  * @param[in] list The array list to copy.
  * @return A new array list with the same element type and values as the 
original array list or NULL if the original
  * array list is NULL or out of memory.
  */
 CELIX_UTILS_EXPORT
+CELIX_OWNERSHIP_RETURNS(celix_array_list)
 celix_array_list_t* celix_arrayList_copy(const celix_array_list_t* list);
 
 /**
diff --git a/libs/utils/include/celix_array_list_encoding.h 
b/libs/utils/include/celix_array_list_encoding.h
index 135372fdc..9a602ef1b 100644
--- a/libs/utils/include/celix_array_list_encoding.h
+++ b/libs/utils/include/celix_array_list_encoding.h
@@ -36,18 +36,18 @@ extern "C" {
  */
 
 /**
- * @brief Flag to indicate that the encoding should be pretty printed. e.g. 
encoded with additional whitespaces, newlines and indentation.
+ * @brief Flag to indicate that the encoding should be pretty printed, e.g., 
encoded with additional whitespaces, newlines and indentation.
  *
- * If this flag is not set, the encoding will be compact. e.g. without 
additional whitespaces, newlines and indentation.
+ * If this flag is not set, the encoding will be compact, e.g., without 
additional whitespaces, newlines and indentation.
  */
 #define CELIX_ARRAY_LIST_ENCODE_PRETTY 0x01
 
 /**
  * @brief Flag to indicate that the encoding should fail if an empty array is 
encountered.
  *
- * If this flag is not set, an empty array will be encoded as an empty json 
array representation("[]").
+ * If this flag is not set, an empty array will be encoded as an empty JSON 
array representation("[]").
  *
- * Although empty arrays are valid in json, they cannot decoded to a valid 
celix_array_list_t.
+ * Although empty arrays are valid in JSON, they cannot be decoded to a valid 
celix_array_list_t.
  */
 #define CELIX_ARRAY_LIST_ENCODE_ERROR_ON_EMPTY_ARRAYS 0x10
 
@@ -56,12 +56,12 @@ extern "C" {
  *
  * If this flag is not set, the encoding will not fail and the NaN and Inf 
value will be ignored.
  *
- * NaN and Inf values are not valid in json, as such celix_array_list_t with 
these values cannot be encoded to json.
+ * NaN and Inf values are not valid in JSON, as such celix_array_list_t with 
these values cannot be encoded to JSON.
  */
 #define CELIX_ARRAY_LIST_ENCODE_ERROR_ON_NAN_INF 0x20
 
 /**
- * @brief Flag to indicate that the encoding should be strict. e.g. fail on 
empty arrays and NaN/Inf values.
+ * @brief Flag to indicate that the encoding should be strict, e.g., fail on 
empty arrays and NaN/Inf values.
  */
 #define CELIX_ARRAY_LIST_ENCODE_STRICT \
     (CELIX_ARRAY_LIST_ENCODE_ERROR_ON_EMPTY_ARRAYS | 
CELIX_ARRAY_LIST_ENCODE_ERROR_ON_NAN_INF)
@@ -70,7 +70,7 @@ extern "C" {
 
 
 /**
- * @brief Encode the given celix_array_list_t as a JSON representation,and 
write it to the given stream.
+ * @brief Encode the given celix_array_list_t as a JSON representation and 
write it to the given stream.
  *
  * The caller is the owner of the stream and is responsible for closing it.
  *
@@ -96,7 +96,7 @@ CELIX_UTILS_EXPORT
 celix_status_t celix_arrayList_saveToStream(const celix_array_list_t* list, 
int encodeFlags, FILE* stream);
 
 /**
- * @brief Encode the given celix_array_list_t as a JSON representation, and 
write it to the given file.
+ * @brief Encode the given celix_array_list_t as a JSON representation and 
write it to the given file.
  *
  * For more information about the encoding, see celix_arrayList_saveToStream.
  *
@@ -138,19 +138,19 @@ celix_status_t celix_arrayList_saveToString(const 
celix_array_list_t* list, int
 /**
  * @brief Flag to indicate that the decoding should fail if an empty array is 
encountered.
  *
- * If this flag is not set, the decoding will not fail and the empty json 
array representation("[]") will be ignored, then a NULL celix_array_list_t* 
will be returned.
+ * If this flag is not set, the decoding will not fail, and the empty JSON 
array representation("[]") will be ignored, then a NULL celix_array_list_t* 
will be returned.
  */
 #define CELIX_ARRAY_LIST_DECODE_ERROR_ON_EMPTY_ARRAYS 0x01
 
 /**
  * @brief Flag to indicate that the decoding should fail if an unsupported 
array type is encountered.
  *
- * If this flag is not set, the decoding will not fail and the unsupported 
array type will be ignored, then a NULL celix_array_list_t* will be returned.
+ * If this flag is not set, the decoding will not fail, and the unsupported 
array type will be ignored, then a NULL celix_array_list_t* will be returned.
  */
 #define CELIX_ARRAY_LIST_DECODE_ERROR_ON_UNSUPPORTED_ARRAYS 0x02
 
 /**
- * @brief Flag to indicate that the decoding should be strict. e.g. fail on 
empty arrays and unsupported array types.
+ * @brief Flag to indicate that the decoding should be strict, e.g., fail on 
empty arrays and unsupported array types.
  *
  */
 #define CELIX_ARRAY_LIST_DECODE_STRICT \
diff --git a/libs/utils/include/celix_cleanup.h 
b/libs/utils/include/celix_cleanup.h
index ec565fd8e..fbb5e2118 100644
--- a/libs/utils/include/celix_cleanup.h
+++ b/libs/utils/include/celix_cleanup.h
@@ -118,10 +118,10 @@ extern "C" {
  */
 #ifdef __cplusplus
 #define celix_steal_ptr(p) \
-    ({ auto __ptr = (p); (p) = NULL; __ptr; })
+    ({ auto celix_ptr_ = (p); (p) = NULL; celix_ptr_; })
 #else
 #define celix_steal_ptr(p) \
-    ({ __auto_type __ptr = (p); (p) = NULL; __ptr; })
+    ({ __auto_type celix_ptr_ = (p); (p) = NULL; celix_ptr_; })
 #endif
 
 
diff --git a/libs/utils/include/celix_compiler.h 
b/libs/utils/include/celix_compiler.h
index 866a92e94..bda61c970 100644
--- a/libs/utils/include/celix_compiler.h
+++ b/libs/utils/include/celix_compiler.h
@@ -55,6 +55,82 @@ extern "C" {
 #define CELIX_HAS_ATTRIBUTE(x) 0
 #endif
 
+/**
+ * CELIX_OWNERSHIP_TAKES(type, idx)
+ *
+ * Expands to the compiler attribute `__attribute__((ownership_takes(type, 
idx)))`
+ * when the compiler supports the `ownership_takes` attribute. This attribute
+ * marks a function as a deallocating function.
+ *
+ * See also:
+ * clang: 
https://clang.llvm.org/docs/AttributeReference.html#ownership-holds-ownership-returns-ownership-takes-clang-static-analyzer
+ *
+ * Parameters:
+ *  - `type`: the type of the allocation: malloc, new, etc. to allow for 
catching mismatched deallocation bugs.
+ *  - `idx`:  1-based index of the parameter that is being deallocated.
+ *
+ * Example:
+ * ```C
+ *  void CELIX_OWNERSHIP_TAKES(owner, 1) free_string(char* ptr);
+ * ```
+ */
+
+#if CELIX_HAS_ATTRIBUTE(ownership_takes)
+#define CELIX_OWNERSHIP_TAKES(type, idx) __attribute__((ownership_takes(type, 
idx)))
+#else
+#define CELIX_OWNERSHIP_TAKES(type, idx)
+#endif
+
+/**
+ * CELIX_OWNERSHIP_RETURNS(type)
+ *
+ * Expands to the compiler attribute `__attribute__((ownership_returns(type, 
idx)))`
+ * when the compiler supports the `ownership_returns` attribute. This attribute
+ * marks a function as an allocating function.
+ *
+ * See also:
+ * clang: 
https://clang.llvm.org/docs/AttributeReference.html#ownership-holds-ownership-returns-ownership-takes-clang-static-analyzer
+ *
+ * Parameters:
+ *  - `type`: the type of the allocation: malloc, new, etc. to allow for 
catching mismatched deallocation bugs.
+ *
+ * Example:
+ * ```C
+ *  char CELIX_OWNERSHIP_RETURNS(owner)* allocate_string(void);
+ * ```
+ */
+#if CELIX_HAS_ATTRIBUTE(ownership_returns)
+#define CELIX_OWNERSHIP_RETURNS(type) __attribute__((ownership_returns(type)))
+#else
+#define CELIX_OWNERSHIP_RETURNS(type)
+#endif
+
+/**
+ * CELIX_OWNERSHIP_HOLDS(type, idx)
+ *
+ * Expands to the compiler attribute `__attribute__((ownership_holds(type, 
idx)))`
+ * when the compiler supports the `ownership_holds` attribute. This attribute
+ * marks that a function takes over the ownership of a piece of memory and 
will free it
+ * at some unspecified point in the future.
+ *
+ * See also:
+ * clang: 
https://clang.llvm.org/docs/AttributeReference.html#ownership-holds-ownership-returns-ownership-takes-clang-static-analyzer
+ *
+ * Parameters:
+ *  - `type`: the type of the allocation: malloc, new, etc. to allow for 
catching mismatched deallocation bugs.
+ *  - `idx`:  1-based index of the parameter whose ownership will be taken 
over.
+ *
+ * Example:
+ * ```C
+ *  void CELIX_OWNERSHIP_HOLDS(owner, 1) hold_string(char* ptr);
+ * ```
+ */
+#if CELIX_HAS_ATTRIBUTE(ownership_holds)
+#define CELIX_OWNERSHIP_HOLDS(type, idx) __attribute__((ownership_holds(type, 
idx)))
+#else
+#define CELIX_OWNERSHIP_HOLDS(type, idx)
+#endif
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/libs/utils/include/celix_convert_utils.h 
b/libs/utils/include/celix_convert_utils.h
index 8458559ed..5272e3054 100644
--- a/libs/utils/include/celix_convert_utils.h
+++ b/libs/utils/include/celix_convert_utils.h
@@ -23,6 +23,7 @@
 #include <stdbool.h>
 
 #include "celix_array_list.h"
+#include "celix_compiler.h"
 #include "celix_errno.h"
 #include "celix_utils_export.h"
 #include "celix_version.h"
@@ -39,8 +40,7 @@ extern "C" {
 /**
  * @brief Convert a string to a boolean.
  *
- * Converts a string to a boolean. White space is ignored and the following 
values are considered booleans (case
- * insensitive): "true', "false".
+ * Converts a string to a boolean. White space is ignored, and the following 
values are considered booleans (case-insensitive): "true", "false".
  *
  * @param[in] val The string to convert.
  * @param[in] defaultValue The default value if the string is not a valid 
boolean.
@@ -60,7 +60,7 @@ CELIX_UTILS_EXPORT bool celix_utils_convertStringToBool(const 
char* val, bool de
 CELIX_UTILS_EXPORT double celix_utils_convertStringToDouble(const char* val, 
double defaultValue, bool* converted);
 
 /**
- * @brief Convert a string to a long.
+ * @brief Convert a string to a long integer.
  *
  * @param[in] val The string to convert.
  * @param[in] defaultValue The default value if the string is not a valid long.
@@ -75,13 +75,13 @@ CELIX_UTILS_EXPORT long 
celix_utils_convertStringToLong(const char* val, long de
  * In case of an error, an error message is added to celix_err.
  *
  * @note This convert function will only convert version strings in the format 
major.minor.micro(.qualifier)?.
- * So the major, minor and micro are required, the qualifier is optional.
+ * So the major, minor, and micro are required, and the qualifier is optional.
  *
  * @param[in] val The string to convert.
  * @param[in] defaultValue The default value if the string is not a valid 
celix_version_t.
  * @param[out] version The converted version. If the string is not a valid 
version, the version will be set to a copy of
  *                     the defaultValue.
- * @return CELIX_SUCCESS if the string is a valid version, 
CELIX_ILLEGAL_ARGUMENT if the string is not a valid version
+ * @return CELIX_SUCCESS if the string is a valid version, 
CELIX_ILLEGAL_ARGUMENT if the string is not a valid version,
  * and CELIX_ENOMEM if memory could not be allocated. Note that on a 
CELIX_ILLEGAL_ARGUMENT the version will be set to a
  * copy of the defaultValue.
  */
@@ -101,7 +101,7 @@ CELIX_UTILS_EXPORT celix_status_t 
celix_utils_convertStringToVersion(const char*
  * @param[in] defaultValue The default value if the string is not a valid "," 
separated list of longs.
  * @param[out] list The converted list. If the string is not a valid list, the 
list will be set to a copy of the
  * defaultValue.
- * @return CELIX_SUCCESS if the string is a valid array list of specified 
entry type, CELIX_ILLEGAL_ARGUMENT if otherwise,
+ * @return CELIX_SUCCESS if the string is a valid array list of the specified 
entry type, CELIX_ILLEGAL_ARGUMENT if otherwise,
  * and CELIX_ENOMEM if memory could not be allocated.
  * Note that on a CELIX_ILLEGAL_ARGUMENT the list will be set to a copy of the 
defaultValue.
  */
@@ -119,10 +119,10 @@ celix_status_t 
celix_utils_convertStringToLongArrayList(const char* val,
  * In case of an error, an error message is added to celix_err.
  *
  * @param[in] val The string to convert.
- * @param[in] defaultValue The default value if the string is not a valid "," 
separated list of doubles.
+ * @param[in] defaultValue The default value if the string is not a valid  
comma-separated list of doubles.
  * @param[out] list The converted list. If the string is not a valid list, the 
list will be set to a copy of the
  * defaultValue.
- * @return CELIX_SUCCESS if the string is a valid array list of specified 
entry type, CELIX_ILLEGAL_ARGUMENT if otherwise,
+ * @return CELIX_SUCCESS if the string is a valid array list of the specified 
entry type, CELIX_ILLEGAL_ARGUMENT if otherwise,
  * and CELIX_ENOMEM if memory could not be allocated.
  * Note that on a CELIX_ILLEGAL_ARGUMENT the list will be set to a copy of the 
defaultValue.
  */
@@ -140,10 +140,10 @@ celix_status_t 
celix_utils_convertStringToDoubleArrayList(const char* val,
  * In case of an error, an error message is added to celix_err.
  *
  * @param[in] val The string to convert.
- * @param[in] defaultValue The default value if the string is not a valid "," 
separated list of booleans.
+ * @param[in] defaultValue The default value if the string is not a valid 
comma-separated list of booleans.
  * @param[out] list The converted list. If the string is not a valid list, the 
list will be set to a copy of the
  * defaultValue.
- * @return CELIX_SUCCESS if the string is a valid array list of specified 
entry type, CELIX_ILLEGAL_ARGUMENT if otherwise,
+ * @return CELIX_SUCCESS if the string is a valid array list of the specified 
entry type, CELIX_ILLEGAL_ARGUMENT if otherwise,
  * and CELIX_ENOMEM if memory could not be allocated.
  * Note that on a CELIX_ILLEGAL_ARGUMENT the list will be set to a copy of the 
defaultValue.
  */
@@ -164,13 +164,13 @@ celix_status_t 
celix_utils_convertStringToBoolArrayList(const char* val,
  * In case of an error, an error message is added to celix_err.
  *
  * @param[in] val The string to convert.
- * @param[in] defaultValue The default value if the string is not a valid "," 
separated list of strings.
- *                         Note that the defaultValue is copied if the string 
is not a valid list of string entries
+ * @param[in] defaultValue The default value if the string is not a valid 
comma-separated list of strings.
+ *                         Note that the defaultValue is copied if the string 
is not a valid list of string entries,
  *                         and the defaultValue is expected to be configured 
with a removed entry callback so the
- * strings are freed.
+ *                         strings are freed.
  * @param[out] list The converted list. If the string is not a valid list, the 
list will be set to a copy of the
  * defaultValue.
- * @return CELIX_SUCCESS if the string is a valid array list of specified 
entry type, CELIX_ILLEGAL_ARGUMENT if otherwise,
+ * @return CELIX_SUCCESS if the string is a valid array list of the specified 
entry type, CELIX_ILLEGAL_ARGUMENT if otherwise,
  * and CELIX_ENOMEM if memory could not be allocated.
  * Note that on a CELIX_ILLEGAL_ARGUMENT the list will be set to a copy of the 
defaultValue.
  */
@@ -183,7 +183,7 @@ celix_status_t 
celix_utils_convertStringToStringArrayList(const char* val,
  * @brief Convert a string to a celix_array_list_t* with celix_version_t* 
entries.
  *
  * The expected format of the string is a "," separated list of 
celix_version_t* entries. Whitespace is ignored.
- * Version entries are created using celix_utils_convertStringToVersion and 
the returned list will be configured to call
+ * Version entries are created using `celix_utils_convertStringToVersion` and 
the returned list will be configured to call
  * celix_version_destroy when entries are removed.
  *
  * In case of an error, an error message is added to celix_err.
@@ -191,11 +191,11 @@ celix_status_t 
celix_utils_convertStringToStringArrayList(const char* val,
  * @param[in] val The string to convert.
  * @param[in] defaultValue The default value if the string is not a valid "," 
separated list of string parseable to
  *                         celix_version_t entries. Note that the defaultValue 
is copied if the string is not a valid
- *                         list of version entries and the defaultValue
+ *                         list of version entries, and the defaultValue
  *                         is expected to be configured with a removed entry 
callback so the versions are freed.
  * @param[out] list The converted list. If the string is not a valid list, the 
list will be set to a copy of the
  * defaultValue.
- * @return CELIX_SUCCESS if the string is a valid array list of specified 
entry type, CELIX_ILLEGAL_ARGUMENT if otherwise,
+ * @return CELIX_SUCCESS if the string is a valid array list of the specified 
entry type, CELIX_ILLEGAL_ARGUMENT if otherwise,
  * and CELIX_ENOMEM if memory could not be allocated.
  * Note that on a CELIX_ILLEGAL_ARGUMENT the list will be set to a copy of the 
defaultValue.
  */
@@ -219,10 +219,9 @@ celix_status_t 
celix_utils_convertStringToVersionArrayList(const char* val,
  *              CELIX_ARRAY_LIST_ELEMENT_TYPE_POINTER.
  */
 CELIX_UTILS_EXPORT
+CELIX_OWNERSHIP_RETURNS(malloc)
 char* celix_utils_arrayListToString(const celix_array_list_t* list);
 
-
-
 #ifdef __cplusplus
 }
 #endif
diff --git a/libs/utils/include/celix_filter.h 
b/libs/utils/include/celix_filter.h
index b7aa690cd..4da67f5a0 100644
--- a/libs/utils/include/celix_filter.h
+++ b/libs/utils/include/celix_filter.h
@@ -22,11 +22,11 @@
  * @brief Header file for the Celix Filter API.
  *
  * #Introduction
- * An Apache Celix filter is a based on LDAP filters, for more information 
about LDAP filters see:
+ * An Apache Celix filter is based on LDAP filters, for more information about 
LDAP filters see:
  *  - https://tools.ietf.org/html/rfc4515
  *  - https://tools.ietf.org/html/rfc1960
  *
- * In short an Apache Celix filter is a tree of filter nodes, parsed from a 
filter string.
+ * In short, an Apache Celix filter is a tree of filter nodes, parsed from a 
filter string.
  * Each node has an operand, an optional attribute string and an optional 
value string.
  * The operand can be one of the following:
  * - `=`: equal
@@ -41,40 +41,40 @@
  * - `&`: and
  * - `|`: or
  *
- The filter string is a list of filter node strings wrapped in parenthesis to 
group filter nodes.
+ The filter string is a list of filter node strings wrapped in parentheses to 
group filter nodes.
  * The following are valid filter strings:
- * - `(key=value)` # Matches if properties contains a entry with key "key" and 
value "value".
- * - `(key>=2)`# Matches if properties contains a entry with key "key" and 
value greater or equal to 2.
- * - `(key=*)` # Matches if properties contains a entry with key "key".
- * - `(!(key=value))` # Matches if properties does not contain a entry with 
key "key" and value "value".
- * - `(&(key1=value1)(key2=value2))` # Matches if properties contains a entry 
with key "key1" and value "value1" and
- *                                   # a entry with key "key2" and value 
"value2".
- * - `(|(key1=value1)(key2=value2))` # Matches if properties contains a entry 
with key "key1" and value "value1" or
- *                                   # a entry with key "key2" and value 
"value2".
+ * - `(key=value)` # Matches if the property set contains an entry with key 
"key" and value "value".
+ * - `(key>=2)`# Matches if the property set contains an entry with key "key" 
and value greater or equal to 2.
+ * - `(key=*)` # Matches if the property set contains an entry with key "key".
+ * - `(!(key=value))` # Matches if the property set does not contain an entry 
with key "key" and value "value".
+ * - `(&(key1=value1)(key2=value2))` # Matches if the property set contains an 
entry with key "key1" and value "value1" and
+ *                                   # an entry with key "key2" and value 
"value2".
+ * - `(|(key1=value1)(key2=value2))` # Matches if the property set contains an 
entry with key "key1" and value "value1" or
+ *                                   # an entry with key "key2" and value 
"value2".
  *
- * Apache Celix filters can be used to match a set of Apache Celix properties 
and such Apache Celix filters should be
+ * Apache Celix filters can be used to match a set of Apache Celix properties, 
and such Apache Celix filters should be
  * used together with a set of properties.
  *
  * #Filter matching and property value types
- * When matching a filter the attribute type of a filter node is used to 
determine the type of the property value and
+ * When matching a filter, the attribute type of the filter node is used to 
determine the type of the property value, and
  * this type is used to compare the property value with the filter attribute 
value.
  * If the property value is of a type that the filter attribute value can be 
parsed to, the filter attribute value the
  * comparison is done with the matching type. If the property value is not of 
a type that the filter attribute value
  * can be parsed to, the comparison is done with the string representation of 
the property value.
  *
- * Internally attribute values will be parsed to a long, double, boolean, 
Apache Celix version and array list of
+ * Internally, attribute values will be parsed to a long, double, boolean, 
Apache Celix version and array list of
  * longs, doubles, booleans, Apache Celix versions and string if possible 
during creation.
  * And these typed attribute values will be used in the to-be-matched property 
value.
  *
- * Example: The filter "(key>20)" and a property set with a long value 3 for 
key "key", will not match and the same
- * filter but with a property set which has a string value "3" for key "key", 
will match.
+ * Example: The filter "(key>20)" and a property set with a long value 3 for 
key "key" will not match, and the same
+ * filter but with a property set which has a string value "3" for key "key" 
will match.
  *
  * #Filter matching and property value arrays
  * If a filter matches a property set entry which has an array value (either a 
long, boolean, double, string or version
- * array) the filter match will check if the array contains a single entry 
which matches the filter attribute value using
+ * array), the filter match will check if the array contains a single entry 
which matches the filter attribute value using
  * the aforementioned "Filter matching and property value types" rules.
  *
- * Filter matching with array is supported for the following operands: "=" 
(including substring), ">=", "<=", ">", "<"
+ * Filter matching with an array is supported for the following operands: "=" 
(including substring), ">=", "<=", ">", "<"
  * and "~=".
  *
  * Example: The filter "(key=3)" will match the property set entry with key 
"key" and a long array list value of
@@ -85,15 +85,15 @@
  * value can contain a `*` to match any character sequence. The filter 
attribute value can also contain a `*` at the
  * start or end of the string to match any character sequence at the start or 
end of the string.
  *
- * A substring filter operand uses the string representation of the property 
value to match with the filter attribute
- * or if the property value is an string array the substring filter operand 
will match if any of the string array values.
+ * A substring filter operand uses the string representation of the property 
value to match with the filter attribute.
+ * If the property value is a string array, the substring filter operand will 
match if any of the string array values matches.
  *
  * Example: The filter "(key=*Smith)" will match the property set entry with 
key "key" and a string value "John Smith".
  *
  * #Approx filter operand
  * The approx filter operand is used to check if the filter attribute value is 
a substring of the property value.
- * A approx filter operand uses the string representation of the property 
value to match with the filter attribute or
- * if the property value is an string array the approx filter operand will 
match if any of the string array values.
+ * An approx filter operand uses the string representation of the property 
value to match with the filter attribute.
+ * If the property value is a string array, the approx filter operand will 
match if any of the string array values matches.
  *
  * Example: The filter "(key~=Smith)" will match the property set entry with 
key "key" and a string value "John Smith".
  */
@@ -156,12 +156,16 @@ struct celix_filter_struct {
  * @param filterStr The filter string. If NULL or "" a match-all "(|)" filter 
is created.
  * @return The created filter or NULL if the filter string is invalid.
  */
-CELIX_UTILS_EXPORT celix_filter_t* celix_filter_create(const char* filterStr);
+CELIX_UTILS_EXPORT
+CELIX_OWNERSHIP_RETURNS(celix_filter)
+celix_filter_t* celix_filter_create(const char* filterStr);
 
 /**
  * @brief Destroy the provided filter. Ignores NULL values.
  */
-CELIX_UTILS_EXPORT void celix_filter_destroy(celix_filter_t* filter);
+CELIX_UTILS_EXPORT
+CELIX_OWNERSHIP_TAKES(celix_filter, 1)
+void celix_filter_destroy(celix_filter_t* filter);
 
 /**
  * @brief Add support for `celix_autoptr`.
@@ -172,7 +176,7 @@ CELIX_DEFINE_AUTOPTR_CLEANUP_FUNC(celix_filter_t, 
celix_filter_destroy)
  * @brief Check whether the provided filter matches the provided properties.
  * @param[in] filter The filter.
  * @param[in] props The properties.
- * @return True if the filter matches the properties, false otherwise. If 
filter is NULL always returns true and
+ * @return True if the filter matches the properties, false otherwise. If 
filter is NULL always returns true, and
  *         if props is NULL, the result is the same as if an empty properties 
set was provided.
  */
 CELIX_UTILS_EXPORT bool celix_filter_match(const celix_filter_t* filter, const 
celix_properties_t* props);
@@ -180,7 +184,7 @@ CELIX_UTILS_EXPORT bool celix_filter_match(const 
celix_filter_t* filter, const c
 /**
  * @brief Check whether the 2 filters are equal.
  *
- * Note that the equals is done based on the parsed filter string and not on 
the provided filter strings.
+ * Note that the equality is done based on the parsed filter string and not on 
the provided filter strings.
  * So the filters parsed from the strings "(key=value)" and " (key=value)" are 
equal.
  *
  * @param[in] filter1 The first filter.
@@ -218,13 +222,13 @@ CELIX_UTILS_EXPORT const char* 
celix_filter_findAttribute(const celix_filter_t*
  *
  * This function recursively examines a filter object to determine if it 
contains  an 'equals' attribute that matches
  * the specified attribute name. The function takes into account the logical 
operators AND, OR, and NOT in the
- * filter structure, and appropriately handles them to assess the presence and 
name of the attribute.
+ * filter structure and appropriately handles them to assess the presence and 
name of the attribute.
  *
  * Example:
- *   using this function for attribute key "key1" on filter "(key1=value1)" 
yields true.
- *   using this function for attribute key "key1" on filter "(!(key1=value1))" 
yields false.
- *   using this function for attribute key "key1" on filter "(key1>=value1)" 
yields false.
- *   using this function for attribute key "key1" on filter 
"(|(key1=value1)(key2=value2))" yields false.
+ *   Using this function for the attribute key "key1" on filter 
"(key1=value1)" yields true.
+ *   Using this function for the attribute key "key1" on filter 
"(!(key1=value1))" yields false.
+ *   Using this function for the attribute key "key1" on filter 
"(key1>=value1)" yields false.
+ *   Using this function for the attribute key "key1" on filter 
"(|(key1=value1)(key2=value2))" yields false.
  *
  * @param[in] filter The filter.
  * @param[in] attribute The attribute to check.
@@ -238,13 +242,13 @@ CELIX_UTILS_EXPORT bool 
celix_filter_hasMandatoryEqualsValueAttribute(const celi
  *
  * This function recursively examines a filter object to determine if it 
contains a specification indicating the
  * mandatory absence of the specified attribute. It takes into account logical 
operators AND, OR, and NOT in the filter
- * structure, and appropriately handles them to assess the absence of the 
attribute.
+ * structure and appropriately handles them to assess the absence of the 
attribute.
  *
  * Examples:
- *   using this function for attribute key "key1" on filter "(!(key1=*))" 
yields true.
- *   using this function for attribute key "key1" on filter "(key1=*)" yields 
false.
- *   using this function for attribute key "key1" on filter "(key1=value)" 
yields false.
- *   using this function for attribute key "key1" on filter 
"(|(!(key1=*))(key2=value2))" yields false.
+ *   Using this function for the attribute key "key1" on filter "(!(key1=*))" 
yields true.
+ *   Using this function for the attribute key "key1" on filter "(key1=*)" 
yields false.
+ *   Using this function for the attribute key "key1" on filter "(key1=value)" 
yields false.
+ *   Using this function for the attribute key "key1" on filter 
"(|(!(key1=*))(key2=value2))" yields false.
  *
  * @param[in] filter The filter to examine.
  * @param[in] attribute The attribute to check for mandatory absence.
diff --git a/libs/utils/include/celix_long_hash_map.h 
b/libs/utils/include/celix_long_hash_map.h
index 73bcf0b94..389498b7b 100644
--- a/libs/utils/include/celix_long_hash_map.h
+++ b/libs/utils/include/celix_long_hash_map.h
@@ -21,6 +21,7 @@
 #define CELIX_LONG_HASH_MAP_H_
 
 #include "celix_cleanup.h"
+#include "celix_compiler.h"
 #include "celix_hash_map_value.h"
 #include "celix_utils_export.h"
 #include "celix_errno.h"
@@ -40,7 +41,7 @@ extern "C" {
 #endif
 
 /**
- * @brief A hash map with uses long as key.
+ * @brief A hash map with uses long as keys.
  *
  * Entries in the hash map can be a pointer, long, double or bool value.
  * All entries should be of the same type.
@@ -60,19 +61,19 @@ typedef struct celix_long_hash_map_iterator {
 } celix_long_hash_map_iterator_t;
 
 /**
- * @brief Optional create options when creating a long hash map.
+ * @brief Optional creation options when creating a long hash map.
  */
 typedef struct celix_long_hash_map_create_options {
     /**
-     * @brief A simple removed callback, which if provided will be called if a 
value is removed
-     * from the hash map. The removed value is provided as pointer.
+     * @brief A simple removed callback that, if provided, is called when a 
value is removed
+     * from the hash map. The removed value is provided as a pointer.
      *
-     * @note only simpleRemovedCallback or removedCallback should be 
configured, if both are configured,
+     * @note Only simpleRemovedCallback or removedCallback should be 
configured, if both are configured,
      * only the simpleRemovedCallback will be used.
      *
      * Default is NULL.
      *
-     * @param[in] removedValue The value that was removed from the hash map. 
This value is no longer used by the
+     * @param[in] value The value that was removed from the hash map. This 
value is no longer used by the
      *                         hash map and can be freed.
      */
     void (*simpleRemovedCallback)(void* value) CELIX_OPTS_INIT;
@@ -85,12 +86,12 @@ typedef struct celix_long_hash_map_create_options {
     void* removedCallbackData CELIX_OPTS_INIT;
 
     /**
-     * @brief A destroy callback, which if provided will be called if a value 
is removed
+     * @brief A removed callback that, if provided, will be called when a 
value is removed
      * from the hash map.
      *
-     * The callback data pointer will be provided as first argument to the 
destroy callback.
+     * The callback data pointer will be provided as the first argument to the 
removed callback.
      *
-     * @note only simpleRemovedCallback or removedCallback should be 
configured, if both are configured,
+     * @note Only simpleRemovedCallback or removedCallback should be 
configured, if both are configured,
      * only the simpleRemovedCallback will be used.
      *
      * Default is NULL.
@@ -105,7 +106,7 @@ typedef struct celix_long_hash_map_create_options {
     /**
      * @brief The initial hash map capacity.
      *
-     * The number of bucket to allocate when creating the hash map.
+     * The number of buckets to allocate when creating the hash map.
      *
      * If 0 is provided, the hash map initial capacity will be 16 (default 
hash map capacity).
      * Default is 0.
@@ -117,11 +118,11 @@ typedef struct celix_long_hash_map_create_options {
      * hash map capacity.
      *
      * The max load factor controls how large the hash map capacity (nr of 
buckets) is compared to the nr of entries
-     * in the hash map. The load factor is an important property of the hash 
map which influences how close the
+     * in the hash map. The load factor is an important property of the hash 
map that influences how closely the
      * hash map performs to O(1) for its get, has and put operations.
      *
-     * If the nr of entries increases above the maxLoadFactor * capacity, the 
hash table capacity will be doubled.
-     * For example a hash map with capacity 16 and load factor 0.75 will 
double its capacity when the 13th entry
+     * If the number of entries increases above the maxLoadFactor * capacity, 
the hash table capacity will be doubled.
+     * For example, a hash map with capacity 16 and load factor 0.75 will 
double its capacity when the 13th entry
      * is added to the hash map.
      *
      * If 0 is provided, the hash map load factor will be 5 (default hash map 
load factor).
@@ -132,7 +133,7 @@ typedef struct celix_long_hash_map_create_options {
 
 #ifndef __cplusplus
 /**
- * @brief C Macro to create a empty string_hash_map_create_options_t type.
+ * @brief C Macro to create an empty string_hash_map_create_options_t type.
  */
 #define CELIX_EMPTY_LONG_HASH_MAP_CREATE_OPTIONS {      \
     .simpleRemovedCallback = NULL,                      \
@@ -146,13 +147,17 @@ typedef struct celix_long_hash_map_create_options {
 /**
  * @brief Creates a new empty hash map with a long as key.
  */
-CELIX_UTILS_EXPORT celix_long_hash_map_t* celix_longHashMap_create();
+CELIX_UTILS_EXPORT
+CELIX_OWNERSHIP_RETURNS(celix_long_hash_map)
+celix_long_hash_map_t* celix_longHashMap_create(void);
 
 /**
- * @brief Creates a new empty long hash map using using the provided hash map 
create options.
+ * @brief Creates a new empty long hash map using the provided hash map create 
options.
  * @param opts The create options, only used during the creation of the hash 
map.
  */
-CELIX_UTILS_EXPORT celix_long_hash_map_t* 
celix_longHashMap_createWithOptions(const celix_long_hash_map_create_options_t* 
opts);
+CELIX_UTILS_EXPORT
+CELIX_OWNERSHIP_RETURNS(celix_long_hash_map)
+celix_long_hash_map_t* celix_longHashMap_createWithOptions(const 
celix_long_hash_map_create_options_t* opts);
 
 /**
  * @brief Clears and then deallocated the hash map.
@@ -161,7 +166,9 @@ CELIX_UTILS_EXPORT celix_long_hash_map_t* 
celix_longHashMap_createWithOptions(co
  *
  * @param map The hashmap
  */
-CELIX_UTILS_EXPORT void celix_longHashMap_destroy(celix_long_hash_map_t* map);
+CELIX_UTILS_EXPORT
+CELIX_OWNERSHIP_TAKES(celix_long_hash_map, 1)
+void celix_longHashMap_destroy(celix_long_hash_map_t* map);
 
 CELIX_DEFINE_AUTOPTR_CLEANUP_FUNC(celix_long_hash_map_t, 
celix_longHashMap_destroy)
 
@@ -184,7 +191,7 @@ CELIX_UTILS_EXPORT size_t celix_longHashMap_size(const 
celix_long_hash_map_t* ma
 CELIX_UTILS_EXPORT celix_status_t celix_longHashMap_put(celix_long_hash_map_t* 
map, long key, void* value);
 
 /**
- * @brief add long entry the long hash map.
+ * @brief Add long entry the long hash map.
  *
  * If the return status is an error, an error message is logged to celix_err.
  *
@@ -197,7 +204,7 @@ CELIX_UTILS_EXPORT celix_status_t 
celix_longHashMap_put(celix_long_hash_map_t* m
 CELIX_UTILS_EXPORT celix_status_t 
celix_longHashMap_putLong(celix_long_hash_map_t* map, long key, long value);
 
 /**
- * @brief add double entry the long hash map.
+ * @brief Add double entry to the long hash map.
  *
  * If the return status is an error, an error message is logged to celix_err.
  *
@@ -210,7 +217,7 @@ CELIX_UTILS_EXPORT celix_status_t 
celix_longHashMap_putLong(celix_long_hash_map_
 CELIX_UTILS_EXPORT celix_status_t 
celix_longHashMap_putDouble(celix_long_hash_map_t* map, long key, double value);
 
 /**
- * @brief add bool entry the long hash map.
+ * @brief Add bool entry the long hash map.
  *
  * If the return status is an error, an error message is logged to celix_err.
  *
@@ -268,10 +275,10 @@ CELIX_UTILS_EXPORT bool celix_longHashMap_getBool(const 
celix_long_hash_map_t* m
 CELIX_UTILS_EXPORT bool celix_longHashMap_hasKey(const celix_long_hash_map_t* 
map, long key);
 
 /**
- * @brief Remove a entry from the hashmap and silently ignore if the hash map 
does not have a entry with the provided
+ * @brief Remove an entry from the hashmap and silently ignore if the hash map 
does not have an entry with the provided
  * key.
  *
- * @note If the hash map was created with a (simple) remove callback, the 
callback will have been called if a entry
+ * @note If the hash map was created with a (simple) remove callback, the 
callback will have been called if an entry
  * for the provided key was present when this function returns.
  *
  * @return True is the value is found and removed.
@@ -288,7 +295,7 @@ CELIX_UTILS_EXPORT void 
celix_longHashMap_clear(celix_long_hash_map_t* map);
 /**
  * @brief Check if the provided string hash maps are equal.
  *
- * Equals means that both maps have the same number of entries and that all 
entries in the first map
+ * Equality means that both maps have the same number of entries and that all 
entries in the first map
  * are also present in the second map and have the same value.
  *
  * @param[in] map1 The first map to compare.
@@ -360,7 +367,7 @@ CELIX_UTILS_EXPORT void 
celix_longHashMapIterator_remove(celix_long_hash_map_ite
 /**
  * @brief Marco to loop over all the entries of a long hash map.
  *
- * Small example of how to use the iterate macro:
+ * Small example of how to use the iterator macro:
  * @code{.c}
  * celix_long_hash_map_t* map = ...
  * CELIX_LONG_HASH_MAP_ITERATE(map, iter) {
diff --git a/libs/utils/include/celix_properties.h 
b/libs/utils/include/celix_properties.h
index 08a2d773b..2c44c8ad2 100644
--- a/libs/utils/include/celix_properties.h
+++ b/libs/utils/include/celix_properties.h
@@ -65,7 +65,7 @@ typedef enum celix_properties_value_type {
     CELIX_PROPERTIES_VALUE_TYPE_ARRAY_LIST =
         6, /**< Property value is an array list. The element type of the array 
list can be
               CELIX_ARRAY_LIST_ELEMENT_TYPE_STRING, 
CELIX_ARRAY_LIST_ELEMENT_TYPE_LONG,
-              CELIX_ARRAY_LIST_ELEMENT_TYPE_DOUBLE, 
CELIX_ARRAY_LIST_ELEMENT_TYPE_BOOL or
+              CELIX_ARRAY_LIST_ELEMENT_TYPE_DOUBLE, 
CELIX_ARRAY_LIST_ELEMENT_TYPE_BOOL, or
               CELIX_ARRAY_LIST_ELEMENT_TYPE_VERSION. */
 } celix_properties_value_type_e;
 
@@ -118,14 +118,18 @@ typedef struct celix_properties_iterator {
  *
  * @return A new empty property set.
  */
-CELIX_UTILS_EXPORT celix_properties_t* celix_properties_create();
+CELIX_UTILS_EXPORT
+CELIX_OWNERSHIP_RETURNS(celix_properties)
+celix_properties_t* celix_properties_create(void);
 
 /**
  * @brief Destroy a property set, freeing all associated resources.
  *
  * @param[in] properties The property set to destroy. If properties is NULL, 
this function will do nothing.
  */
-CELIX_UTILS_EXPORT void celix_properties_destroy(celix_properties_t* 
properties);
+CELIX_UTILS_EXPORT
+CELIX_OWNERSHIP_TAKES(celix_properties, 1)
+void celix_properties_destroy(celix_properties_t* properties);
 
 CELIX_DEFINE_AUTOPTR_CLEANUP_FUNC(celix_properties_t, celix_properties_destroy)
 
@@ -205,9 +209,12 @@ CELIX_UTILS_EXPORT celix_status_t 
celix_properties_set(celix_properties_t* prope
  *         and CELIX_ILLEGAL_ARGUMENT if the provided key or value is NULL.
  *         When an error status is returned, the key and value will be freed 
by this function.
  */
-CELIX_UTILS_EXPORT celix_status_t celix_properties_assign(celix_properties_t* 
properties,
-                                                                  char* key,
-                                                                  char* value);
+CELIX_UTILS_EXPORT
+CELIX_OWNERSHIP_HOLDS(malloc, 2)
+CELIX_OWNERSHIP_HOLDS(malloc, 3)
+celix_status_t celix_properties_assign(celix_properties_t *properties,
+                                       char *key,
+                                       char *value);
 
 /**
  * @brief Get the value of a property, if the property is set and the 
underlying type is a string.
@@ -255,22 +262,24 @@ CELIX_UTILS_EXPORT celix_status_t 
celix_properties_setString(celix_properties_t*
  *
  * The set property type will be CELIX_PROPERTIES_VALUE_TYPE_STRING.
  *
- * This function take ownership of the provided string.
+ * This function takes ownership of the provided string.
  * If the return status is an error, an error message is logged to celix_err.
  *
  * @param[in] properties The property set to modify.
  * @param[in] key The key of the property to set.
- * @param[in] value The value to assign. The function take ownership of the 
provided version. Cannot be NULL.
+ * @param[in] value The value to assign. The function takes ownership of the 
provided version. Cannot be NULL.
  * @return CELIX_SUCCESS if the operation was successful, CELIX_ENOMEM if 
there was not enough memory to set the entry
  *         and CELIX_ILLEGAL_ARGUMENT if the provided key is NULL. When an 
error status is returned,
  *         the string will be free by this function.
  */
-CELIX_UTILS_EXPORT celix_status_t 
celix_properties_assignString(celix_properties_t* properties,
-                                                                const char* 
key,
-                                                                char* value);
+CELIX_UTILS_EXPORT
+CELIX_OWNERSHIP_HOLDS(malloc, 3)
+celix_status_t celix_properties_assignString(celix_properties_t* properties,
+                                             const char *key,
+                                             char *value);
 
 /**
- * @brief Get the value of a property, if the property is set and the 
underlying type is a long.
+ * @brief Get the value of a property if the property is set and the 
underlying type is a long.
  * @param[in] properties The property set to search.
  * @param[in] key The key of the property to get.
  * @param[in] defaultValue The value to return if the property is not set or 
the value is not a long.
@@ -425,16 +434,18 @@ CELIX_UTILS_EXPORT celix_status_t 
celix_properties_setVersion(celix_properties_t
  *                    takes ownership of the provided version. Cannot be NULL.
  * @return CELIX_SUCCESS if the operation was successful, CELIX_ENOMEM if 
there was not enough memory to set the entry
  *         and CELIX_ILLEGAL_ARGUMENT if the provided key is NULL. When an 
error status is returned,
- *         the version will be destroy with celix_version_destroy by this 
function.
+ *         the version will be destroyed with celix_version_destroy by this 
function.
  */
-CELIX_UTILS_EXPORT celix_status_t 
celix_properties_assignVersion(celix_properties_t* properties,
-                                                                 const char* 
key,
-                                                                 
celix_version_t* version);
+CELIX_UTILS_EXPORT
+CELIX_OWNERSHIP_HOLDS(celix_version, 3)
+celix_status_t celix_properties_assignVersion(celix_properties_t *properties,
+                                              const char *key,
+                                              celix_version_t* version);
 
 /**
  * @brief Get the Celix version value of a property without copying.
  *
- * This function provides a non-owning, read-only access to a Celix version 
contained in the properties.
+ * This function provides non-owning, read-only access to a Celix version 
contained in the properties.
  * It returns a const pointer to the Celix version value associated with the 
specified key.
  * This function does not perform any conversion from a string property value 
to a Celix version.
  *
@@ -460,7 +471,7 @@ CELIX_UTILS_EXPORT const celix_version_t* 
celix_properties_getVersion(const celi
  * @param[in] key The key of the property to get.
  * @param[in] defaultValue The value to return if the property is not set or 
if the value is not a Celix version.
  * @param[out] version A copy of the found version, a new parsed version, or a 
copy of the default value if the
- *                 property is not set, its value is not an version or its 
value cannot be converted to an version.
+ *                 property is not set, its value is not a version, or its 
value cannot be converted to a version.
  * @return CELIX_SUCCESS if the operation was successful, CELIX_ENOMEM if 
there was not enough memory to create the
  *        version. Note if the key is not found, the return status is still 
CELIX_SUCCESS.
  */
@@ -496,28 +507,30 @@ CELIX_UTILS_EXPORT celix_status_t 
celix_properties_setArrayList(celix_properties
  *
  * This function stores a reference to the provided celix_array_list_t object 
in the property set and takes
  * ownership of the array.
- * If an error occurs, the error status is returned, the provided array is 
destroyed and a
+ * If an error occurs, the error status is returned, the provided array is 
destroyed, and a
  * message is logged to celix_err.
  *
  * @param[in] properties The property set to modify.
  * @param[in] key The key of the property to set.
  * @param[in] values An array list of long values to assign to the property. 
Ownership of the array is transferred
- *                   to the properties set. Cannot be NULL.
+ *                   to the property set. Cannot be NULL.
  * @return CELIX_SUCCESS if the operation was successful, CELIX_ENOMEM if 
there was not enough memory to set the entry,
- *         and CELIX_ILLEGAL_ARGUMENT if the provided key is NULL, values is 
NULL or the array list type is
- *         invalid. On error, the provided array list is destroyed.
+ *         and CELIX_ILLEGAL_ARGUMENT if the provided key is NULL, values is 
NULL, or the array list type is
+ *         invalid. In error, the provided array list is destroyed.
  */
-CELIX_UTILS_EXPORT celix_status_t 
celix_properties_assignArrayList(celix_properties_t* properties,
-                                                                   const char* 
key,
-                                                                   
celix_array_list_t* values);
+CELIX_UTILS_EXPORT
+CELIX_OWNERSHIP_HOLDS(celix_array_list, 3)
+celix_status_t celix_properties_assignArrayList(celix_properties_t *properties,
+                                                const char *key,
+                                                celix_array_list_t *values);
 
 /**
  * @brief Get the property value as an array without copying.
  *
- * This function provides a non-owning, read-only access to a array property 
value.
+ * This function provides non-owning, read-only access to an array property 
value.
  * It returns a const pointer to the array. If the property is not set or its 
value is not an array, NULL is returned.
  *
- * The returned array will have a element type of:
+ * The returned array will have an element type of:
  *  - CELIX_ARRAY_LIST_ELEMENT_TYPE_STRING
  *  - CELIX_ARRAY_LIST_ELEMENT_TYPE_LONG
  *  - CELIX_ARRAY_LIST_ELEMENT_TYPE_DOUBLE
@@ -540,10 +553,10 @@ CELIX_UTILS_EXPORT const celix_array_list_t* 
celix_properties_getArrayList(const
  * This function retrieves the value of a property, interpreting it as an 
array of longs. If the underlying type of the
  * property value is a long array, a copy of the array is returned. If the 
underlying type is a string, the string is
  * converted to an array of longs if possible.
- * If the property is not set, its value is not an array of longs or its value 
cannot be converted to a long array,
+ * If the property is not set, its value is not an array of longs, or its 
value cannot be converted to a long array,
  * the default value is returned as a copy.
  *
- * An celix err is logged if the default value is needed and not an array list 
with long values.
+ * A celix ERR is logged if the default value is needed and not an array list 
with long values.
  *
  * @param[in] properties The property set to search.
  * @param[in] key The key of the property to get.
@@ -565,7 +578,7 @@ CELIX_UTILS_EXPORT celix_status_t 
celix_properties_getAsLongArrayList(const celi
 /**
  * @brief Get the property value as an array of longs without copying.
  *
- * This function provides a non-owning, read-only access to an array of longs 
property value.
+ * This function provides non-owning, read-only access to an array of long 
property values.
  * It returns a const pointer to the array. If the property is not set or its 
value is not an array of longs,
  * NULL is returned.
  *
@@ -576,14 +589,14 @@ CELIX_UTILS_EXPORT celix_status_t 
celix_properties_getAsLongArrayList(const celi
  *         is not set or its value is not an array of longs. The returned 
pointer should not be modified or freed.
  */
 CELIX_UTILS_EXPORT const celix_array_list_t* 
celix_properties_getLongArrayList(const celix_properties_t* properties,
-                                                                            
const char* key);
+                                                                               
const char *key);
 
 /**
  * @brief Get a property value as an array of doubles, making a copy of the 
array.
  *
  * This function retrieves the value of a property, interpreting it as an 
array of doubles. If the underlying type of
  * the property value is a double array, a copy of the array is returned. If 
the underlying type is a string, the string
- * is converted to an array of doubles if possible. If the property is not 
set, its value is not an array of doubles or
+ * is converted to an array of doubles if possible. If the property is not 
set, its value is not an array of doubles, or
  * its value cannot be converted to a double array, the default value is 
returned as a copy.
  *
  * @param[in] properties The property set to search.
@@ -607,7 +620,7 @@ CELIX_UTILS_EXPORT celix_status_t 
celix_properties_getAsDoubleArrayList(const ce
 /**
  * @brief Get the property value as an array of doubles without copying.
  *
- * This function provides a non-owning, read-only access to an array of 
doubles property value.
+ * This function provides non-owning, read-only access to an array of doubles 
property value.
  * It returns a const pointer to the array. If the property is not set or its 
value is not an array of doubles,
  * NULL is returned.
  *
@@ -626,9 +639,9 @@ CELIX_UTILS_EXPORT const celix_array_list_t* 
celix_properties_getDoubleArrayList
  * This function retrieves the value of a property, interpreting it as an 
array of booleans. If the underlying type of
  * the property value is a boolean array, a copy of the array is returned. If 
the underlying type is a string, the
  * string is converted to an array of booleans if possible. If the property is 
not set, its value is not an array of
- * booleans or its value cannot be converted to a boolean array, the default 
value is returned as a copy.
+ * booleans, or its value cannot be converted to a boolean array, the default 
value is returned as a copy.
  *
- * An celix err is logged if the default value is needed and not an array list 
with boolean values.
+ * A celix ERR is logged if the default value is needed and not an array list 
with boolean values.
  *
  * @param[in] properties The property set to search.
  * @param[in] key The key of the property to get.
@@ -651,7 +664,7 @@ CELIX_UTILS_EXPORT celix_status_t 
celix_properties_getAsBoolArrayList(const celi
 /**
  * @brief Get the property value as an array of booleans without copying.
  *
- * This function provides a non-owning, read-only access to a array of 
booleans property value.
+ * This function provides non-owning, read-only access to an array of boolean 
property values.
  * It returns a const pointer to the array. If the property is not set or its 
value is not an array of booleans,
  * NULL is returned.
  *
@@ -668,13 +681,13 @@ CELIX_UTILS_EXPORT const celix_array_list_t* 
celix_properties_getBoolArrayList(c
  *
  * This function retrieves the value of a property, interpreting it as an 
array of strings. If the underlying type of
  * the property value is a string array, a copy of the array is returned. If 
the underlying type is a string, the string
- * is converted to an array of strings if possible. If the property is not 
set, its value is not an array of strings or
+ * is converted to an array of strings if possible. If the property is not 
set, its value is not an array of strings, or
  *  its value cannot be converted to a string array, the default value is 
returned as a copy.
  *
  * The returned array list is configured with a remove callback so that the 
destruction of the array list will also
  * free the strings in the array list.
  *
- * An celix err is logged if the default value is needed and not an array list 
with string values.
+ * A celix ERR is logged if the default value is needed and not an array list 
with string values.
  *
  * @param[in] properties The property set to search.
  * @param[in] key The key of the property to get.
@@ -697,7 +710,7 @@ CELIX_UTILS_EXPORT celix_status_t 
celix_properties_getAsStringArrayList(const ce
 /**
  * @brief Get the property value as an array of strings without copying.
  *
- * This function provides a non-owning, read-only access to an array of string 
property value.
+ * This function provides non-owning, read-only access to an array of string 
property values.
  * It returns a const pointer to the array. If the property is not set or its 
value is not an array of strings,
  * NULL is returned.
  *
@@ -716,13 +729,13 @@ CELIX_UTILS_EXPORT const celix_array_list_t* 
celix_properties_getStringArrayList
  * This function retrieves the value of a property, interpreting it as an 
array of celix_version_t* entries. If the
  * underlying type of the property value is a celix_version_t* array, a copy 
of the array is returned. If the underlying
  * type is a string, the string is converted to an array of celix_version_t* 
if possible. If the property is not set,
- * its value is not an array of celix_version_t* entries or its value cannot 
be converted to a celix_version_t* array,
+ * its value is not an array of celix_version_t* entries, or its value cannot 
be converted to a celix_version_t* array,
  * the default value is returned as a copy.
  *
  * The returned array list is configured with a remove callback so that the 
destruction of the array list will also
  * free the celix_version_t entries in the array list.
  *
- * An celix err is logged if the default value is needed and not an array list 
with celix_version_t values.
+ * A celix ERR is logged if the default value is needed and not an array list 
with celix_version_t values.
  *
  * @param[in] properties The property set to search.
  * @param[in] key The key of the property to get.
@@ -745,8 +758,8 @@ CELIX_UTILS_EXPORT celix_status_t 
celix_properties_getAsVersionArrayList(const c
 /**
  * @brief Get the property value as an array of celix_version_t entries 
without copying.
  *
- * This function provides a non-owning, read-only access to an array of 
celix_version_t property value.
- * entries. It returns a const pointer to the array. If the property is not 
set or its value is not an array of
+ * This function provides non-owning, read-only access to an array of 
celix_version_t entries.
+ * It returns a const pointer to the array. If the property is not set or its 
value is not an array of
  * celix_version_t entries, NULL is returned.
  *
  * @param[in] properties The property set to search.
@@ -759,10 +772,10 @@ CELIX_UTILS_EXPORT const celix_array_list_t* 
celix_properties_getVersionArrayLis
                                                                                
   const char* key);
 
 /**
- * @brief Set the value of a property based on the provided property entry, 
maintaining underlying type.
+ * @brief Set the value of a property based on the provided property entry, 
maintaining the underlying type.
  *
  * The typed entry value will be copied, which means that this function will 
use the entry.typed.strValue,
- * entry.typed.longValue, entry.typed.doubleValue, entry.typed.boolValue or 
entry.typed.versionValue depending on
+ * entry.typed.longValue, entry.typed.doubleValue, entry.typed.boolValue, or 
entry.typed.versionValue depending on
  * the entry.valueType. The entry.strValue will be ignored.
  *
  * If the return status is an error, an error message is logged to celix_err.
@@ -787,14 +800,16 @@ CELIX_UTILS_EXPORT celix_status_t 
celix_properties_setEntry(celix_properties_t*
 CELIX_UTILS_EXPORT void celix_properties_unset(celix_properties_t* properties, 
const char* key);
 
 /**
- * @brief Make a copy of a properties set.
+ * @brief Make a copy of a property set.
  *
  * If the return status is an error, an error message is logged to celix_err.
  *
  * @param[in] properties The property set to copy.
  * @return A copy of the given property set.
  */
-CELIX_UTILS_EXPORT celix_properties_t* celix_properties_copy(const 
celix_properties_t* properties);
+CELIX_UTILS_EXPORT
+CELIX_OWNERSHIP_RETURNS(celix_properties)
+celix_properties_t* celix_properties_copy(const celix_properties_t* 
properties);
 
 /**
  * @brief Get the number of properties in a property set.
@@ -807,7 +822,7 @@ CELIX_UTILS_EXPORT size_t celix_properties_size(const 
celix_properties_t* proper
 /**
  * @brief Check whether the provided property sets are equal.
  *
- * Equals means that both property sets have the same number of properties and 
that all properties in the first set
+ * Equality means that both property sets have the same number of properties 
and that all properties in the first set
  * are also present in the second set and have the same value.
  *
  * @param[in] props1 The first property set to compare.
@@ -888,9 +903,9 @@ CELIX_UTILS_EXPORT bool 
celix_propertiesIterator_equals(const celix_properties_i
 
 /**
  * @brief Flag to indicate that the encoded output should be pretty; e.g. 
encoded with additional whitespaces,
- * newlines and indentation.
+ * newlines, and indentation.
  *
- * If this flag is not set, the encoded output will compact; e.g. without 
additional whitespaces, newlines and
+ * If this flag is not set, the encoded output will be compact; e.g. without 
additional whitespaces, newlines, and
  * indentation.
  */
 #define CELIX_PROPERTIES_ENCODE_PRETTY 0x01
@@ -962,7 +977,7 @@ CELIX_UTILS_EXPORT bool 
celix_propertiesIterator_equals(const celix_properties_i
 /**
  * @brief Flag to indicate that the encoding should fail if the JSON 
representation will contain empty arrays.
  *
- * Although empty arrays are valid in JSON, they cannot be decoded to a valid 
properties array entry and as such
+ * Although empty arrays are valid in JSON, they cannot be decoded to a valid 
properties array entry, and as such
  * empty arrays properties entries are not encoded.
  *
  * If this flag is set, the encoding will fail if the JSON representation will 
contain empty arrays and if this flag
@@ -973,9 +988,9 @@ CELIX_UTILS_EXPORT bool 
celix_propertiesIterator_equals(const celix_properties_i
 /**
  * @brief Flag to indicate that the encoding should fail if the JSON 
representation will contain NaN or Inf values.
  *
- * NaN, Inf and -Inf are not valid JSON values and as such properties entries 
with these values are not encoded.
+ * NaN, Inf, and -Inf are not valid JSON values, and as such properties 
entries with these values are not encoded.
  *
- * If this flag is set, the encoding will fail if the JSON representation will 
contain NaN or Inf values and if this
+ * If this flag is set, the encoding will fail if the JSON representation will 
contain NaN or Inf values, and if this
  * flag is not set, the encoding will not fail and the NaN and Inf entries 
will be ignored.
  */
 #define CELIX_PROPERTIES_ENCODE_ERROR_ON_NAN_INF 0x40
@@ -994,17 +1009,17 @@ CELIX_UTILS_EXPORT bool 
celix_propertiesIterator_equals(const celix_properties_i
  *
  * Properties are encoded as a JSON object.
  *
- * If no encoding style flag is set or when the 
CELIX_PROPERTIES_ENCODE_FLAT_STYLE flag is set, properties
+ * If no encoding style flag is set or when the 
CELIX_PROPERTIES_ENCODE_FLAT_STYLE flag is set, property
  * entries are written as top level field entries.
  *
- * If the CELIX_PROPERTIES_ENCODE_NESTED_STYLE flag is set, properties entry 
keys are split on '/' and nested in
+ * If the CELIX_PROPERTIES_ENCODE_NESTED_STYLE flag is set, property entry 
keys are split on '/' and nested in
  * JSON objects. This leads to a more natural JSON representation, but if 
there are colliding properties keys (e.g.
- * `{"key": "value1", "key/with/slash": "value2"}`), not all properties 
entries will be written.
+ * `{"key": "value1", "key/with/slash": "value2"}`), not all property entries 
will be written.
  *
- * With all encoding styles, the empty array properties entries are ignored, 
because they cannot be decoded to a valid
- * properties array entry.
+ * With all encoding styles, the empty array properties entries are ignored 
because they cannot be decoded to a valid
+ * property array entry.
  *
- * Properties type entries are encoded as follows:
+ * Property entry types are encoded as follows:
  * - CELIX_PROPERTIES_TYPE_STRING: The value is encoded as a JSON string.
  * - CELIX_PROPERTIES_TYPE_LONG: The value is encoded as a JSON number.
  * - CELIX_PROPERTIES_TYPE_DOUBLE: The value is encoded as a JSON number.
@@ -1013,7 +1028,7 @@ CELIX_UTILS_EXPORT bool 
celix_propertiesIterator_equals(const celix_properties_i
  * - CELIX_PROPERTIES_TYPE_VERSION: The value is encoded as a JSON string with 
a "version<" prefix and a ">" suffix
  * (e.g. "version<1.2.3>").
  *
- * For a overview of the possible encode flags, see the 
CELIX_PROPERTIES_ENCODE_* flags documentation.
+ * For an overview of the possible encode flags, see the 
CELIX_PROPERTIES_ENCODE_* flags documentation.
  * The default encoding style is a compact and flat JSON representation.
  *
  * @param properties The properties object to encode.
@@ -1070,17 +1085,17 @@ CELIX_UTILS_EXPORT celix_status_t 
celix_properties_saveToString(const celix_prop
  *
  * E.g. `{"key": "value", "key": "value2"}` is a duplicate key.
  *
- * If this flag is set, the decoding will fail if the input contains a 
duplicate key and if this flag is not set, the
+ * If this flag is set, the decoding will fail if the input contains a 
duplicate key, and if this flag is not set, the
  * decoding will not fail and the last entry will be used.
  */
 #define CELIX_PROPERTIES_DECODE_ERROR_ON_DUPLICATES 0x01
 
 /**
- * @brief Flag to indicate that the decoding should fail if the input contains 
entry that collide on property keys.
+ * @brief Flag to indicate that the decoding should fail if the input contains 
entry that collides on property keys.
  *
  * E.g. `{"obj/key": "value", "obj": {"key": "value2"}}` is a collision.
  *
- * If this flag is set, the decoding will fail if the input contains a 
collision and if this flag is not set, the
+ * If this flag is set, the decoding will fail if the input contains a 
collision, and if this flag is not set, the
  * decoding will not fail and the last entry will be used.
  */
 #define CELIX_PROPERTIES_DECODE_ERROR_ON_COLLISIONS 0x02
@@ -1092,7 +1107,7 @@ CELIX_UTILS_EXPORT celix_status_t 
celix_properties_saveToString(const celix_prop
  *
  * Note arrays with null values are handled by the 
CELIX_PROPERTIES_DECODE_ERROR_ON_UNSUPPORTED_ARRAYS flag.
  *
- * If this flag is set, the decoding will fail if the input contains a null 
value and if this flag is not set, the
+ * If this flag is set, the decoding will fail if the input contains a null 
value, and if this flag is not set, the
  * decoding will not fail and the JSON null entry will be ignored.
  */
 #define CELIX_PROPERTIES_DECODE_ERROR_ON_NULL_VALUES 0x04
@@ -1103,9 +1118,9 @@ CELIX_UTILS_EXPORT celix_status_t 
celix_properties_saveToString(const celix_prop
  *
  * E.g. `{"key": []}` is an empty array.
  *
- * Note that empty arrays are valid in JSON, but not cannot be decoded to a 
valid properties array entry.
+ * Note that empty arrays are valid in JSON, but not cannot be decoded to a 
valid property array entry.
  *
- * If this flag is set, the decoding will fail if the input contains an empty 
array and if this flag is not set, the
+ * If this flag is set, the decoding will fail if the input contains an empty 
array, and if this flag is not set, the
  * decoding will not fail and the JSON empty array entry will be ignored.
  */
 #define CELIX_PROPERTIES_DECODE_ERROR_ON_EMPTY_ARRAYS 0x08
@@ -1113,7 +1128,7 @@ CELIX_UTILS_EXPORT celix_status_t 
celix_properties_saveToString(const celix_prop
 /**
  * @brief Flag to indicate that the decoding should fail if the input contains 
unsupported arrays.
  *
- * Unsupported arrays are arrays that contain JSON objects, multiple arrays, 
arrays with null values and
+ * Unsupported arrays are arrays that contain JSON objects, multiple arrays, 
arrays with null values, and
  * mixed arrays.
  * E.g.
  * - `{"key": [{"nested": "value"}]}` (array with JSON object)
@@ -1153,28 +1168,28 @@ CELIX_UTILS_EXPORT celix_status_t 
celix_properties_saveToString(const celix_prop
  * The stream is expected to be a valid readable stream and is not reset or 
closed by this function.
  * The content of the stream is expected to be in the format of a JSON object.
  *
- * For decoding a single JSON object is decoded to a properties object.
+ * For decoding, a single JSON object is decoded to a properties object.
  *
  * The keys of the JSON object are used as
- * properties keys and the values of the JSON object are used as properties 
values. If there are nested
+ * property keys, and the values of the JSON object are used as property 
values. If there are nested
  * JSON objects, the keys are concatenated with a '/' separator (e.g. `{"key": 
{"nested": "value"}}` will be
  * decoded to a properties object with a single entry with key `key/nested` 
and (string) value `value`).
  *
- * Because properties keys are created by concatenating the JSON keys, there 
there could be collisions
+ * Because property keys are created by concatenating the JSON keys, there 
could be collisions
  * (e.g. `{"obj/key": "value", "obj": {"key": "value2"}}`, two entries with 
the key `obj/key`. In this case
  * the last decoded JSON entry will be used.
  *
- * Properties entry types are determined by the JSON value type:
+ * Property entry types are determined by the JSON value type:
  * - JSON string values are decoded as string properties entries.
  * - JSON number values are decoded as long or double properties entries, 
depending on the value.
  * - JSON boolean values are decoded as boolean properties entries.
- * - jSON string values with a "version<" prefix and a ">" suffix are decoded 
as version properties entries (e.g.
+ * - JSON string values with a "version<" prefix and a ">" suffix are decoded 
as version properties entries (e.g.
  * "version<1.2.3>").
  * - JSON array values are decoded as array properties entries. The array can 
contain any of the above types, but mixed
  * arrays are not supported.
  * - JSON null values are ignored.
  *
- * For a overview of the possible decode flags, see the 
CELIX_PROPERTIES_DECODE_* flags documentation.
+ * For an overview of the possible decode flags, see the 
CELIX_PROPERTIES_DECODE_* flags documentation.
  *
  * @param[in] stream The input stream to parse.
  * @param[in] decodeFlags The flags to use when decoding the input string.
@@ -1197,7 +1212,7 @@ CELIX_UTILS_EXPORT celix_status_t 
celix_properties_loadFromStream(FILE* stream,
  * The content of the filename file is expected to be in the format of a JSON 
object.
  * For what can and cannot be parsed, see celix_properties_loadFromStream 
documentation.
  *
- * For a overview of the possible decode flags, see the 
CELIX_PROPERTIES_DECODE_* flags documentation.
+ * For an overview of the possible decode flags, see the 
CELIX_PROPERTIES_DECODE_* flags documentation.
  *
  * If an error occurs, the error status is returned and a message is logged to 
celix_err.
  *
@@ -1222,7 +1237,7 @@ CELIX_UTILS_EXPORT celix_status_t 
celix_properties_load(const char* filename,
  * The input string is expected to be in the format of a JSON object.
  * For what can and cannot be parsed, see celix_properties_loadFromStream 
documentation.
  *
- * For a overview of the possible decode flags, see the 
CELIX_PROPERTIES_DECODE_* flags documentation.
+ * For an overview of the possible decode flags, see the 
CELIX_PROPERTIES_DECODE_* flags documentation.
  *
  * If an error occurs, the error status is returned and a message is logged to 
celix_err.
  *
diff --git a/libs/utils/include/celix_string_hash_map.h 
b/libs/utils/include/celix_string_hash_map.h
index 1f0972ce0..55cc99cad 100644
--- a/libs/utils/include/celix_string_hash_map.h
+++ b/libs/utils/include/celix_string_hash_map.h
@@ -21,6 +21,7 @@
 #define CELIX_STRING_HASH_MAP_H_
 
 #include "celix_cleanup.h"
+#include "celix_compiler.h"
 #include "celix_hash_map_value.h"
 #include "celix_utils_export.h"
 #include "celix_errno.h"
@@ -39,7 +40,7 @@ extern "C" {
 #endif
 
 /**
- * @brief A hash map with uses string (const char*) as key.
+ * @brief A hash map with uses string (const char*) as keys.
  *
  * Entries in the hash map can be a pointer, long, double or bool value.
  * All entries should be of the same type.
@@ -59,14 +60,14 @@ typedef struct celix_string_hash_map_iterator {
 } celix_string_hash_map_iterator_t;
 
 /**
- * @brief Optional create options when creating a string hash map.
+ * @brief Optional creation options when creating a string hash map.
  */
 typedef struct celix_string_hash_map_create_options {
     /**
-     * @brief A simple removed callback, which if provided will be called if a 
value is removed
-     * from the hash map. The removed value is provided as pointer.
+     * @brief A simple removed callback that, if provided, will be called when 
a value is removed
+     * from the hash map. The removed value is provided as a pointer.
      *
-     * @note only simpleRemovedCallback or removedCallback should be 
configured, if both are configured,
+     * @note Only simpleRemovedCallback or removedCallback should be 
configured, if both are configured,
      * only the simpledRemoveCallback will be used.
      *
      * Default is NULL.
@@ -84,19 +85,19 @@ typedef struct celix_string_hash_map_create_options {
     void* removedCallbackData CELIX_OPTS_INIT;
 
     /**
-     * @brief A removed callback, which if provided will be called if a value 
is removed
+     * @brief A removed callback that, if provided, will be called when a 
value is removed
      * from the hash map.
      *
-     * The callback data pointer will be provided as first argument to the 
destroy callback.
+     * The callback data pointer will be provided as the first argument to the 
removed callback.
      *
-     * @note only simpleRemovedCallback or removedCallback should be 
configured, if both are configured,
+     * @note Only simpleRemovedCallback or removedCallback should be 
configured, if both are configured,
      * only the simpledRemoveCallback will be used.
      *
      * Default is NULL.
      *
      * @param[in] data The void pointer to the data that was provided when the 
callback was set as removedCallbackData.
      * @param[in] removedKey The key of the value that was removed from the 
hash map.
-     *                       Note that the removedKey can still be in use if 
the a value entry for the same key is
+     *                       Note that the removedKey can still be in use if a 
value entry for the same key is
      *                       replaced, so this callback should not free the 
removedKey.
      * @param[in] removedValue The value that was removed from the hash map. 
This value is no longer used by the
      *                         hash map and can be freed.
@@ -104,10 +105,10 @@ typedef struct celix_string_hash_map_create_options {
     void (*removedCallback)(void* data, const char* removedKey, 
celix_hash_map_value_t removedValue) CELIX_OPTS_INIT;
 
     /**
-     * @brief A removed key callback, which if provided will be called if a 
key is no longer used in the hash map.
+     * @brief A removed key callback that, if provided, will be called when a 
key is no longer used in the hash map.
      *
      * @param[in] data The void pointer to the data that was provided when the 
callback was set as removedCallbackData.
-     * @param[in] key The key that is no longer used in the hash map. if 
`storeKeysWeakly` was configured as true,
+     * @param[in] key The key that is no longer used in the hash map. If 
`storeKeysWeakly` was configured as true,
      *                the key can be freed.
      */
     void (*removedKeyCallback)(void* data, char* key) CELIX_OPTS_INIT;
@@ -116,7 +117,7 @@ typedef struct celix_string_hash_map_create_options {
      * @brief If set to true, the string hash map will not make of copy of the 
keys and assumes
      * that the keys are in scope/memory for the complete lifecycle of the 
string hash map.
      *
-     * When keys are stored weakly it is the caller responsibility to check if 
a key is already in use
+     * When keys are stored weakly, it is the caller's responsibility to check 
if a key is already in use
      * (celix_stringHashMap_hasKey).
      *
      * If the key is already in use, the celix_stringHashMap_put* will not 
store the provided key and will
@@ -124,9 +125,9 @@ typedef struct celix_string_hash_map_create_options {
      * If the key is not already in use, the celix_stringHashMap_put* will 
store the provided key and the caller
      * should not free the provided key.
      *
-     * Uf a celix_stringHashMap_put* returns a error, the caller may free the 
provided key.
+     * Uf a celix_stringHashMap_put* returns an error, the caller may free the 
provided key.
      *
-     * @note This changes the default behaviour of the 
celix_stringHashMap_put* functions.
+     * @note This changes the default behavior of the celix_stringHashMap_put* 
functions.
      *
      * Default is false.
      */
@@ -135,7 +136,7 @@ typedef struct celix_string_hash_map_create_options {
     /**
      * @brief The initial hash map capacity.
      *
-     * The number of bucket to allocate when creating the hash map.
+     * The number of buckets to allocate when creating the hash map.
      *
      * If 0 is provided, the hash map initial capacity will be 16 (default 
hash map capacity).
      * Default is 0.
@@ -147,11 +148,11 @@ typedef struct celix_string_hash_map_create_options {
       * hash map capacity.
       *
       * The max load factor controls how large the hash map capacity (nr of 
buckets) is compared to the nr of entries
-      * in the hash map. The load factor is an important property of the hash 
map which influences how close the
+      * in the hash map. The load factor is an important property of the hash 
map that influences how closely the
       * hash map performs to O(1) for its get, has and put operations.
       *
-      * If the nr of entries increases above the maxLoadFactor * capacity, the 
hash table capacity will be doubled.
-      * For example a hash map with capacity 16 and load factor 0.75 will 
double its capacity when the 13th entry
+      * If the number of entries increases above the maxLoadFactor * capacity, 
the hash table capacity will be doubled.
+      * For example, a hash map with capacity 16 and load factor 0.75 will 
double its capacity when the 13th entry
       * is added to the hash map.
       *
       * If 0 is provided, the hash map load factor will be 0.75 (default hash 
map load factor).
@@ -162,7 +163,7 @@ typedef struct celix_string_hash_map_create_options {
 
 #ifndef __cplusplus
 /**
- * @brief C Macro to create a empty string_hash_map_create_options_t type.
+ * @brief C Macro to create an empty string_hash_map_create_options_t type.
  */
 #define CELIX_EMPTY_STRING_HASH_MAP_CREATE_OPTIONS {    \
     .simpleRemovedCallback = NULL,                      \
@@ -176,15 +177,19 @@ typedef struct celix_string_hash_map_create_options {
 #endif
 
 /**
- * @brief Creates a new empty hash map with a 'const char*' as key.
+ * @brief Creates a new empty hash map with string keys.
  */
-CELIX_UTILS_EXPORT celix_string_hash_map_t* celix_stringHashMap_create();
+CELIX_UTILS_EXPORT
+CELIX_OWNERSHIP_RETURNS(celix_string_hash_map)
+celix_string_hash_map_t* celix_stringHashMap_create(void);
 
 /**
- * @brief Creates a new empty string hash map using using the provided hash 
map create options.
+ * @brief Creates a new empty string hash map using the provided hash map 
create options.
  * @param opts The create options, only used during the creation of the hash 
map.
  */
-CELIX_UTILS_EXPORT celix_string_hash_map_t* 
celix_stringHashMap_createWithOptions(const 
celix_string_hash_map_create_options_t* opts);
+CELIX_UTILS_EXPORT
+CELIX_OWNERSHIP_RETURNS(celix_string_hash_map)
+celix_string_hash_map_t* celix_stringHashMap_createWithOptions(const 
celix_string_hash_map_create_options_t* opts);
 
 /**
  * @brief Clears and then deallocated the hash map.
@@ -193,7 +198,9 @@ CELIX_UTILS_EXPORT celix_string_hash_map_t* 
celix_stringHashMap_createWithOption
  *
  * @param map The hashmap
  */
-CELIX_UTILS_EXPORT void celix_stringHashMap_destroy(celix_string_hash_map_t* 
map);
+CELIX_UTILS_EXPORT
+CELIX_OWNERSHIP_TAKES(celix_string_hash_map, 1)
+void celix_stringHashMap_destroy(celix_string_hash_map_t* map);
 
 CELIX_DEFINE_AUTOPTR_CLEANUP_FUNC(celix_string_hash_map_t, 
celix_stringHashMap_destroy)
 
@@ -216,7 +223,7 @@ CELIX_UTILS_EXPORT size_t celix_stringHashMap_size(const 
celix_string_hash_map_t
 CELIX_UTILS_EXPORT celix_status_t 
celix_stringHashMap_put(celix_string_hash_map_t* map, const char* key, void* 
value);
 
 /**
- * @brief add long entry the string hash map.
+ * @brief Add long entry the string hash map.
  *
  * If the return status is an error, an error message is logged to celix_err.
  *
@@ -229,19 +236,20 @@ CELIX_UTILS_EXPORT celix_status_t 
celix_stringHashMap_put(celix_string_hash_map_
 CELIX_UTILS_EXPORT celix_status_t 
celix_stringHashMap_putLong(celix_string_hash_map_t* map, const char* key, long 
value);
 
 /**
- * @brief add double entry the string hash map.
+ * @brief Add double entry to the string hash map.
  *
  * If the return status is an error, an error message is logged to celix_err.
  *
  * @param map The hashmap.
  * @param key  The key to use. The hashmap will create a copy if needed.
+ * @param value The value to store with the key.
  * @return celix_status_t CELIX_SUCCESS if the entry was added, CELIX_ENOMEM 
if no memory could be allocated for the
  *         entry.
  */
 CELIX_UTILS_EXPORT celix_status_t 
celix_stringHashMap_putDouble(celix_string_hash_map_t* map, const char* key, 
double value);
 
 /**
- * @brief add bool entry the string hash map.
+ * @brief Add bool entry the string hash map.
  *
  * If the return status is an error, an error message is logged to celix_err.
  *
@@ -298,10 +306,10 @@ CELIX_UTILS_EXPORT bool celix_stringHashMap_getBool(const 
celix_string_hash_map_
 CELIX_UTILS_EXPORT bool celix_stringHashMap_hasKey(const 
celix_string_hash_map_t* map, const char* key);
 
 /**
- * @brief Remove a entry from the hashmap and silently ignore if the hash map 
does not have a entry with the provided
+ * @brief Remove an entry from the hashmap and silently ignore if the hash map 
does not have an entry with the provided
  * key.
  *
- * @note If the hash map was created with a (simple) remove callback, the 
callback will have been called if a entry
+ * @note If the hash map was created with a (simple) remove callback, the 
callback will have been called if an entry
  * for the provided key was present when this function returns.
  *
  * @return True is the value is found and removed.
@@ -318,10 +326,10 @@ CELIX_UTILS_EXPORT void 
celix_stringHashMap_clear(celix_string_hash_map_t* map);
 /**
  * @brief Check if the provided string hash maps are equal.
  *
- * Equals means that both maps have the same number of entries and that all 
entries in the first map
+ * Equality means that both maps have the same number of entries and that all 
entries in the first map
  * are also present in the second map and have the same value.
  *
- * The value are compared using memcpy, so for pointer values the pointer 
value is compared and not the value itself.
+ * The values are compared using memcmp, so for pointer values the pointer 
value is compared and not the value itself.
  *
  * @param[in] map1 The first map to compare.
  * @param[in] map2 The second map to compare.
@@ -363,8 +371,6 @@ CELIX_UTILS_EXPORT void 
celix_stringHashMapIterator_next(celix_string_hash_map_i
 /**
  * @brief Compares two celix_string_hash_map_iterator_t objects for equality.
  *
- * The value are compared using memcpy, so for pointer values the pointer 
value is compared and not the value itself.
- *
  * @param[in] iterator The first iterator to compare.
  * @param[in] other The second iterator to compare.
  * @return true if the iterators point to the same entry in the same hash map, 
false otherwise.
@@ -395,7 +401,7 @@ CELIX_UTILS_EXPORT void 
celix_stringHashMapIterator_remove(celix_string_hash_map
 /**
  * @brief Marco to loop over all the entries of a string hash map.
  *
- * Small example of how to use the iterate macro:
+ * Small example of how to use the iterator macro:
  * @code{.c}
  * celix_string_hash_map_t* map = ...
  * CELIX_STRING_HASH_MAP_ITERATE(map, iter) {
diff --git a/libs/utils/include/celix_utils.h b/libs/utils/include/celix_utils.h
index 19a4fd94e..b0326bc94 100644
--- a/libs/utils/include/celix_utils.h
+++ b/libs/utils/include/celix_utils.h
@@ -24,6 +24,7 @@
 extern "C" {
 #endif
 
+// ReSharper disable once CppUnusedIncludeDirective
 #include <time.h>
 #include <stdarg.h>
 #include <stdbool.h>
@@ -40,7 +41,9 @@ extern "C" {
  * The strdup is limited to the CELIX_UTILS_MAX_STRLEN and uses strndup to 
achieve this.
  * @return a copy of the string (including null terminator).
  */
-CELIX_UTILS_EXPORT char* celix_utils_strdup(const char *str);
+CELIX_UTILS_EXPORT
+CELIX_OWNERSHIP_RETURNS(malloc)
+char* celix_utils_strdup(const char *str);
 
 /**
  * Returns the length of the provided string with a max of 
CELIX_UTILS_MAX_STRLEN.
@@ -50,40 +53,37 @@ CELIX_UTILS_EXPORT char* celix_utils_strdup(const char 
*str);
 CELIX_UTILS_EXPORT size_t celix_utils_strlen(const char *str);
 
 /**
- * @brief Creates a hash from a string
- * @param string
- * @return hash
- */
-CELIX_UTILS_EXPORT unsigned int celix_utils_stringHash(const char* string);
-
-/**
- * The proposed buffer size to use for celix_utils_writeOrCreateString with a 
buffer on the stcck.
+ * The proposed buffer size to use for celix_utils_writeOrCreateString with a 
buffer on the stack.
  */
 #define CELIX_DEFAULT_STRING_CREATE_BUFFER_SIZE 512
 
 /**`
- * @brief Format a string to the provided buffer or a newly allocated buffer 
if the provided buffer is to small.
+ * @brief Format a string to the provided buffer or a newly allocated buffer 
if the provided buffer is too small.
  * @param[in,out] buffer The buffer to write the formatted string to.
  * @param[in] bufferSize The size of the buffer.
  * @param[in] format The format string.
  * @param[in] ... The arguments for the format string.
- * @return The formatted string in the provided buffer or a newly allocated 
buffer if the provided buffer is to small.
- * @retval NULL if a allocation was needed, but failed.
+ * @return The formatted string in the provided buffer or a newly allocated 
buffer if the provided buffer is too small.
+ * @retval NULL if an allocation was needed, but failed.
  */
-CELIX_UTILS_EXPORT char* celix_utils_writeOrCreateString(char* buffer, size_t 
bufferSize, const char* format, ...)
-    __attribute__((format(printf, 3, 4)));
+CELIX_UTILS_EXPORT
+CELIX_OWNERSHIP_RETURNS(celix_buffer_string)
+__attribute__((format(printf, 3, 4)))
+char* celix_utils_writeOrCreateString(char* buffer, size_t bufferSize, const 
char* format, ...);
 
 /**
- * @brief Format a string to the provided buffer or a newly allocated buffer 
if the provided buffer is to small.
+ * @brief Format a string to the provided buffer or a newly allocated buffer 
if the provided buffer is too small.
  * @param[in,out] buffer The buffer to write the formatted string to.
  * @param[in] bufferSize The size of the buffer.
  * @param[in] format The format string.
  * @param[in] formatArgs The arguments for the format string.
- * @return The formatted string in the provided buffer or a newly allocated 
buffer if the provided buffer is to small.
- * @retval NULL if a allocation was needed, but failed.
+ * @return The formatted string in the provided buffer or a newly allocated 
buffer if the provided buffer is too small.
+ * @retval NULL if an allocation was needed, but failed.
  */
-CELIX_UTILS_EXPORT char* celix_utils_writeOrCreateVString(char* buffer, size_t 
bufferSize, const char* format, va_list formatArgs)
-__attribute__((format(printf, 3, 0)));
+CELIX_UTILS_EXPORT
+CELIX_OWNERSHIP_RETURNS(celix_buffer_string)
+__attribute__((format(printf, 3, 0)))
+char* celix_utils_writeOrCreateVString(char* buffer, size_t bufferSize, const 
char* format, va_list formatArgs);
 
 /**
  * @brief Free the provided str if the str is not equal to the provided buffer.
@@ -91,7 +91,9 @@ __attribute__((format(printf, 3, 0)));
  * @param buffer The buffer to compare the str to.
  * @param str The string to free if it is not equal to the buffer.
  */
-CELIX_UTILS_EXPORT void celix_utils_freeStringIfNotEqual(const char* buffer, 
char* str);
+CELIX_UTILS_EXPORT
+CELIX_OWNERSHIP_TAKES(celix_buffer_string, 2)
+void celix_utils_freeStringIfNotEqual(const char* buffer, char* str);
 
 /**
  * @brief Guard for a string created with celix_utils_writeOrCreateString, 
celix_utils_writeOrCreateVString.
@@ -141,6 +143,8 @@ static CELIX_UNUSED inline celix_utils_string_guard_t 
celix_utils_stringGuard_in
  *
  * @param guard The guard to de-initialize.
  */
+// ReSharper disable once CppParameterMayBeConstPtrOrRef
+// ReSharper disable once CppDFAUnreachableFunctionCall
 static CELIX_UNUSED inline void 
celix_utils_stringGuard_deinit(celix_utils_string_guard_t* guard) {
     celix_utils_freeStringIfNotEqual(guard->buffer, guard->string);
 }
@@ -153,7 +157,7 @@ 
CELIX_DEFINE_AUTO_CLEANUP_CLEAR_FUNC(celix_utils_string_guard_t, celix_utils_str
 CELIX_UTILS_EXPORT bool celix_utils_stringEquals(const char* a, const char* b);
 
 /**
- * Check if the provided string contains a whitespace (spaces, tabs, etc).
+ * Check if the provided string contains a whitespace (spaces, tabs, etc.).
  * The check is based on `isspace`.
  */
 CELIX_UTILS_EXPORT bool celix_utils_containsWhitespace(const char* s);
@@ -161,17 +165,20 @@ CELIX_UTILS_EXPORT bool 
celix_utils_containsWhitespace(const char* s);
 /**
  * @brief Returns a trimmed string.
  *
- * This function will remove any leading and trailing whitespaces (' ', '\t', 
etc based on isspace) from the
+ * This function will remove any leading and trailing whitespaces (' ', '\t', 
etc. based on isspace) from the
  * input string.
  *
  * @param[in] string The input string to be trimmed.
  * @return A trimmed version of the input string. The caller is responsible 
for freeing the memory of this string.
  */
-CELIX_UTILS_EXPORT char* celix_utils_trim(const char* string);
+CELIX_UTILS_EXPORT
+CELIX_OWNERSHIP_RETURNS(malloc)
+char* celix_utils_trim(const char* string);
+
 /**
  * @brief Trims the provided string in place.
  *
- * The trim will remove any leading and trailing whitespaces (' ', '\t', etc 
based on `isspace`)/
+ * The trim will remove any leading and trailing whitespaces (' ', '\t', etc. 
based on `isspace`)/
  * @param string the string to be trimmed.
  * @return string.
  */
@@ -182,34 +189,36 @@ CELIX_UTILS_EXPORT char* celix_utils_trimInPlace(char* 
string);
  */
 CELIX_UTILS_EXPORT bool celix_utils_isStringNullOrEmpty(const char* s);
 
-/** @brief create a C identifier from the provided string by replacing each 
non-alphanumeric character with a
+/** @brief Create a C identifier from the provided string by replacing each 
non-alphanumeric character with an
  * underscore.
  *
  * If the first character is a digit, a prefix underscore will also be added.
  * Will return NULL if the input is NULL or an empty string.
  *
- * @param string the input string to make a C identifier for.
- * @return new newly allocated string or NULL if the input was wrong. The 
caller is owner of the returned string.
+ * @param s the input string to make a C identifier for.
+ * @return new newly allocated string or NULL if the input was wrong. The 
caller is the owner of the returned string.
  */
-CELIX_UTILS_EXPORT char* celix_utils_makeCIdentifier(const char* s);
+CELIX_UTILS_EXPORT
+CELIX_OWNERSHIP_RETURNS(malloc)
+char* celix_utils_makeCIdentifier(const char* s);
 
 
 /**
  * @brief Extract a local name and namespace from a fully qualified name using 
the provided namespace separator.
- * so fully qualified name = celix::extra::lb, namespace separator = "::" -> 
local name = lb, namespace = celix::extra
+ * So fully qualified name = celix::extra::lb, namespace separator = "::" -> 
local name = lb, namespace = celix::extra
  *
- * Note that if no namespace is present the output for namespace will be NULL.
+ * Note that if no namespace is present, the output for namespace will be NULL.
  *
  * @param fullyQualifiedName    The fully qualified name to split
  * @param namespaceSeparator    The namespace separator
- * @param outLocalName          A output argument for the local name part. 
Caller is owner of the data.
- * @param outNamespace          A output argument for the (optional) namespace 
part. Caller is owner of the data.
+ * @param outLocalName          An output argument for the local name part. 
Caller is the owner of the data.
+ * @param outNamespace          An output argument for the (optional) 
namespace part. Caller is the owner of the data.
  */
 CELIX_UTILS_EXPORT void 
celix_utils_extractLocalNameAndNamespaceFromFullyQualifiedName(const char 
*fullyQualifiedName, const char *namespaceSeparator, char **outLocalName, char 
**outNamespace);
 
 /**
  * @brief Returns the diff in seconds between tBegin and tEnd.
- * @param tBegin The begin time.
+ * @param tBegin The beginning time.
  * @param tEnd   The end time.
  * @return       Diff in seconds.
  */
@@ -231,7 +240,7 @@ CELIX_UTILS_EXPORT struct timespec 
celix_delayedTimespec(const struct timespec*
 
 /**
  * @brief Returns the elapsed time - in seconds - relative to the startTime
- * using the clock for the provided clockid.
+ * using the clock for the provided clock id.
  */
 CELIX_UTILS_EXPORT double celix_elapsedtime(clockid_t clockId, struct timespec 
startTime);
 
@@ -239,7 +248,7 @@ CELIX_UTILS_EXPORT double celix_elapsedtime(clockid_t 
clockId, struct timespec s
  * @brief Compare two time arguments.
  * @param[in] a The first timespec.
  * @param[in] b The second timespec.
- * @return 0 if equal, -1 if a is before b and 1 if a is after b.
+ * @return 0 if equal, -1 if @p a is before @p b and 1 if @p a is after @p b.
  */
 CELIX_UTILS_EXPORT int celix_compareTime(const struct timespec* a, const 
struct timespec* b);
 
@@ -258,7 +267,7 @@ CELIX_UTILS_EXPORT unsigned int 
celix_utils_stringHash(const char* string);
  * If the service rankings are the same, but the svcId of A is smaller (older 
service) -> return -1:
  * (smaller A is sorted before B)
  *
- * And vica versa.
+ * And vice versa.
  */
 CELIX_UTILS_EXPORT int celix_utils_compareServiceIdsAndRanking(long svcIdA, 
long svcRankA, long svcIdB, long svcRankB);
 
diff --git a/libs/utils/include/celix_version.h 
b/libs/utils/include/celix_version.h
index 7c36b39a1..1b7a2df57 100644
--- a/libs/utils/include/celix_version.h
+++ b/libs/utils/include/celix_version.h
@@ -25,6 +25,7 @@
 
 #include "celix_version_type.h"
 #include "celix_cleanup.h"
+#include "celix_compiler.h"
 #include "celix_utils_export.h"
 #include "celix_errno.h"
 
@@ -55,26 +56,32 @@ extern "C" {
  *        the empty string.
  * @return The created version or NULL if the input was incorrect or memory 
could not be allocated.
  */
-CELIX_UTILS_EXPORT celix_version_t* celix_version_create(int major, int minor, 
int micro, const char* qualifier);
+CELIX_UTILS_EXPORT
+CELIX_OWNERSHIP_RETURNS(celix_version)
+celix_version_t* celix_version_create(int major, int minor, int micro, const 
char* qualifier);
 
 /**
  * @brief Destroy a celix_version_t*.
  * @param version The version to destroy.
  */
-CELIX_UTILS_EXPORT void celix_version_destroy(celix_version_t* version);
+CELIX_UTILS_EXPORT
+CELIX_OWNERSHIP_TAKES(celix_version, 1)
+void celix_version_destroy(celix_version_t* version);
 
 CELIX_DEFINE_AUTOPTR_CLEANUP_FUNC(celix_version_t, celix_version_destroy)
 
 /**
  * @brief Create a copy of <code>version</code>.
  *
- * If the provided version is NULL a NULL pointer is returned.
+ * If the provided version is NULL, a NULL pointer is returned.
  * If the return is NULL, an error message is logged to celix_err.
  *
  * @param[in] version The version to copy
  * @return the copied version
  */
-CELIX_UTILS_EXPORT celix_version_t* celix_version_copy(const celix_version_t* 
version);
+CELIX_UTILS_EXPORT
+CELIX_OWNERSHIP_RETURNS(celix_version)
+celix_version_t* celix_version_copy(const celix_version_t* version);
 
 /**
  * @brief Create a version identifier from the specified string.
@@ -92,14 +99,16 @@ CELIX_UTILS_EXPORT celix_version_t* 
celix_version_copy(const celix_version_t* ve
  * alpha ::= [a..zA..Z]
  * </pre>
  *
- * There must be no whitespace in version.
+ * There must be no whitespace in a version.
  *
  * If the return is NULL, an error message is logged to celix_err.
  *
  * @param[in] versionStr String representation of the version identifier.
  * @return The created version or NULL if the input was invalid or memory 
could not be allocated.
  */
-CELIX_UTILS_EXPORT celix_version_t* 
celix_version_createVersionFromString(const char *versionStr);
+CELIX_UTILS_EXPORT
+CELIX_OWNERSHIP_RETURNS(celix_version)
+celix_version_t* celix_version_createVersionFromString(const char *versionStr);
 
 /**
  * @brief Parse a version string into a version object.
@@ -139,9 +148,11 @@ CELIX_UTILS_EXPORT celix_status_t 
celix_version_parse(const char *versionStr, ce
 CELIX_UTILS_EXPORT celix_status_t celix_version_tryParse(const char* 
versionStr, celix_version_t** version);
 
 /**
- * @brief Create empty version "0.0.0".
+ * @brief Create an empty version "0.0.0".
  */
-CELIX_UTILS_EXPORT celix_version_t* celix_version_createEmptyVersion();
+CELIX_UTILS_EXPORT
+CELIX_OWNERSHIP_RETURNS(celix_version)
+celix_version_t* celix_version_createEmptyVersion(void);
 
 /**
  * @brief Gets the major version number of a celix version.
@@ -184,13 +195,13 @@ CELIX_UTILS_EXPORT const char* 
celix_version_getQualifier(const celix_version_t*
  * major components are equal and its minor component is less than the other
  * version's minor component, or the major and minor components are equal
  * and its micro component is less than the other version's micro component,
- * or the major, minor and micro components are equal and it's qualifier
+ * or the major, minor, and micro components are equal, and it's qualifier
  * component is less than the other version's qualifier component (using
  * <code>String.compareTo</code>).
  *
  * <p>
  * A version is considered to be <b>equal to</b> another version if the
- * major, minor and micro components are equal and the qualifier component
+ * major, minor, and micro components are equal and the qualifier component
  * is equal (using <code>String.compareTo</code>).
  *
  * @param version The <code>celix_version_t*</code> to be compared with 
<code>compare</code>.
@@ -209,17 +220,19 @@ CELIX_UTILS_EXPORT unsigned int celix_version_hash(const 
celix_version_t* versio
  * @brief Return the string representation of <code>version</code> identifier.
  *
  * The format of the version string will be <code>major.minor.micro</code>
- * if qualifier is the empty string or
+ * if the qualifier is the empty string or
  * <code>major.minor.micro.qualifier</code> otherwise.
  *
  * If the return is NULL, an error message is logged to celix_err.
  *
  * @return The string representation of this version identifier.
  * @param version The <code>celix_version_t*</code> to get the string 
representation from.
- * @return Pointer to the string (char *) in which the result will be placed. 
Caller is owner of the string.
+ * @return Pointer to the string (char *) in which the result will be placed. 
Caller is the owner of the string.
  *         NULL if memory could not be allocated.
  */
-CELIX_UTILS_EXPORT char* celix_version_toString(const celix_version_t* 
version);
+CELIX_UTILS_EXPORT
+CELIX_OWNERSHIP_RETURNS(malloc)
+char* celix_version_toString(const celix_version_t* version);
 
 /**
  * @brief Fill a given string with the string representation of the given 
version.
@@ -232,26 +245,26 @@ CELIX_UTILS_EXPORT char* celix_version_toString(const 
celix_version_t* version);
 CELIX_UTILS_EXPORT bool celix_version_fillString(const celix_version_t* 
version, char *str, size_t strLen);
 
 /**
- * @brief Check if two versions are semantically compatible.
+ * @brief Check if the two versions are semantically compatible.
  *
  * <p>
  * The user version is compatible with the provider version if the provider 
version is in the range
  * [user_version, next_major_from_user_version)
  *
- * @param version The user <code>celix_version_t*</code> .
- * @param version The reference provider <code>celix_version_t*</code> .
+ * @param user The user <code>celix_version_t*</code> .
+ * @param provider The reference provider <code>celix_version_t*</code> .
  * @return Boolean indicating if the versions are compatible
  */
 CELIX_UTILS_EXPORT bool celix_version_isCompatible(const celix_version_t* 
user, const celix_version_t* provider);
 
 /**
- * @brief Check if two versions are semantically compatible.
+ * @brief Check if the two versions are semantically compatible.
  *
  * <p>
  * The user version is compatible with the provider version if the provider 
version is in the range
  * [user_version, next_major_from_user_version)
  *
- * @param version The user <code>celix_version_t*</code> .
+ * @param user The user <code>celix_version_t*</code> .
  * @param providerMajorVersionPart The major part of the provider version
  * @param provideMinorVersionPart The minor part of the provider version
  * @return Boolean indicating if the versions are compatible
diff --git a/libs/utils/include/celix_version_range.h 
b/libs/utils/include/celix_version_range.h
index cddfbc78b..dddff7790 100644
--- a/libs/utils/include/celix_version_range.h
+++ b/libs/utils/include/celix_version_range.h
@@ -28,6 +28,7 @@
 #include "celix_utils_export.h"
 #include "celix_errno.h"
 #include "celix_cleanup.h"
+#include "celix_compiler.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -36,25 +37,32 @@ extern "C" {
 /**
  * Creates a new <code>celix_version_range_t*</code>.
  *
- * @param low Lower bound version
+ * @param low Lower-bound version
  * @param isLowInclusive True if lower bound should be included in the range
- * @param high Upper bound version
- * @param isHighInclusive True if upper bound should be included in the range
- * @param versionRange The created range
+ * @param high Upper-bound version
+ * @param isHighInclusive True if the upper-bound should be included in the 
range
  * @return The service range or NULL if the service range could not be created
  */
-CELIX_UTILS_EXPORT celix_version_range_t*
+CELIX_UTILS_EXPORT
+CELIX_OWNERSHIP_RETURNS(celix_version_range)
+CELIX_OWNERSHIP_HOLDS(celix_version, 1)
+CELIX_OWNERSHIP_HOLDS(celix_version, 3)
+celix_version_range_t*
 celix_versionRange_createVersionRange(celix_version_t* low, bool 
isLowInclusive, celix_version_t* high, bool isHighInclusive);
 
 /**
  * Creates an infinite version range using ::version_createEmptyVersion for 
the low version,
- *     NULL for the high version and high and low inclusive set to true.
+ *     NULL for the high version, and both bounds are inclusive.
  *
  * @return The created range
  */
-CELIX_UTILS_EXPORT celix_version_range_t* 
celix_versionRange_createInfiniteVersionRange();
+CELIX_UTILS_EXPORT
+CELIX_OWNERSHIP_RETURNS(celix_version_range)
+celix_version_range_t* celix_versionRange_createInfiniteVersionRange(void);
 
-CELIX_UTILS_EXPORT void celix_versionRange_destroy(celix_version_range_t* 
range);
+CELIX_UTILS_EXPORT
+CELIX_OWNERSHIP_TAKES(celix_version_range, 1)
+void celix_versionRange_destroy(celix_version_range_t* range);
 
 CELIX_DEFINE_AUTOPTR_CLEANUP_FUNC(celix_version_range_t, 
celix_versionRange_destroy)
 
@@ -87,15 +95,15 @@ CELIX_UTILS_EXPORT bool 
celix_versionRange_isHighInclusive(const celix_version_r
  * Retrieves whether the lower bound version from the given range
  *
  * @param versionRange The range
- * @param The lower bound version.
+ * @return The lower-bound version.
  */
 CELIX_UTILS_EXPORT celix_version_t* celix_versionRange_getLowVersion(const 
celix_version_range_t* versionRange);
 
 /**
- * Retrieves whether the upper bound version from the given range
+ * Retrieves whether the upper-bound version from the given range
  *
  * @param versionRange The range
- * @return The upper bound version.
+ * @return The upper-bound version.
  */
 CELIX_UTILS_EXPORT celix_version_t* celix_versionRange_getHighVersion(const 
celix_version_range_t* versionRange);
 
@@ -121,17 +129,19 @@ CELIX_UTILS_EXPORT celix_version_t* 
celix_versionRange_getHighVersion(const celi
 CELIX_UTILS_EXPORT celix_version_range_t* celix_versionRange_parse(const char 
*rangeString);
 
 /**
- * Returns the LDAP filter for a version range. Caller is owner of the 
returned string.
+ * Returns the LDAP filter for a version range. Caller is the owner of the 
returned string.
  *
  * @param range                         The version range used as input for 
the LDAP filer
- * @param serviceVersionPropertyName    The service version name to be used in 
the filter (i.e. service.version)
+ * @param serviceVersionAttributeName   The service version name to be used in 
the filter (i.e., service.version)
  * @return LDAP filter string if valid, NULL otherwise
  */
-CELIX_UTILS_EXPORT char* celix_versionRange_createLDAPFilter(const 
celix_version_range_t* range, const char *serviceVersionAttributeName);
+CELIX_UTILS_EXPORT
+CELIX_OWNERSHIP_RETURNS(malloc)
+char* celix_versionRange_createLDAPFilter(const celix_version_range_t* range, 
const char *serviceVersionAttributeName);
 
 /**
- * construct a LDAP filter for the provided version range.
- * The string will be created in the provided buffer, if the buffer is big 
enough.
+ * Construct an LDAP filter for the provided version range.
+ * The string will be created in the provided buffer if the buffer is big 
enough.
  *
  * @return True if parse successful, False otherwise.
  */
diff --git a/libs/utils/src/array_list.c b/libs/utils/src/array_list.c
index 361525f2e..61af31918 100644
--- a/libs/utils/src/array_list.c
+++ b/libs/utils/src/array_list.c
@@ -234,31 +234,31 @@ static celix_array_list_t* 
celix_arrayList_createTypedArray(celix_array_list_ele
     return celix_arrayList_createWithOptions(&opts);
 }
 
-celix_array_list_t* celix_arrayList_create() {
+celix_array_list_t* celix_arrayList_create(void) {
     return 
celix_arrayList_createTypedArray(CELIX_ARRAY_LIST_ELEMENT_TYPE_UNDEFINED);
 }
 
-celix_array_list_t* celix_arrayList_createPointerArray() {
+celix_array_list_t* celix_arrayList_createPointerArray(void) {
     return 
celix_arrayList_createTypedArray(CELIX_ARRAY_LIST_ELEMENT_TYPE_POINTER);
 }
 
-celix_array_list_t* celix_arrayList_createStringArray() {
+celix_array_list_t* celix_arrayList_createStringArray(void) {
     return 
celix_arrayList_createTypedArray(CELIX_ARRAY_LIST_ELEMENT_TYPE_STRING);
 }
 
-celix_array_list_t* celix_arrayList_createLongArray() {
+celix_array_list_t* celix_arrayList_createLongArray(void) {
     return 
celix_arrayList_createTypedArray(CELIX_ARRAY_LIST_ELEMENT_TYPE_LONG);
 }
 
-celix_array_list_t* celix_arrayList_createDoubleArray() {
+celix_array_list_t* celix_arrayList_createDoubleArray(void) {
     return 
celix_arrayList_createTypedArray(CELIX_ARRAY_LIST_ELEMENT_TYPE_DOUBLE);
 }
 
-celix_array_list_t* celix_arrayList_createBoolArray() {
+celix_array_list_t* celix_arrayList_createBoolArray(void) {
     return 
celix_arrayList_createTypedArray(CELIX_ARRAY_LIST_ELEMENT_TYPE_BOOL);
 }
 
-celix_array_list_t* celix_arrayList_createVersionArray() {
+celix_array_list_t* celix_arrayList_createVersionArray(void) {
     return 
celix_arrayList_createTypedArray(CELIX_ARRAY_LIST_ELEMENT_TYPE_VERSION);
 }
 
diff --git a/libs/utils/src/celix_hash_map.c b/libs/utils/src/celix_hash_map.c
index bf36c3093..3e7ade626 100644
--- a/libs/utils/src/celix_hash_map.c
+++ b/libs/utils/src/celix_hash_map.c
@@ -467,7 +467,7 @@ celix_string_hash_map_t* 
celix_stringHashMap_createWithOptions(const celix_strin
     return celix_steal_ptr(map);
 }
 
-celix_string_hash_map_t* celix_stringHashMap_create() {
+celix_string_hash_map_t* celix_stringHashMap_create(void) {
     celix_string_hash_map_create_options_t opts = 
CELIX_EMPTY_STRING_HASH_MAP_CREATE_OPTIONS;
     return celix_stringHashMap_createWithOptions(&opts);
 }
@@ -496,7 +496,7 @@ celix_long_hash_map_t* 
celix_longHashMap_createWithOptions(const celix_long_hash
     return celix_steal_ptr(map);
 }
 
-celix_long_hash_map_t* celix_longHashMap_create() {
+celix_long_hash_map_t* celix_longHashMap_create(void) {
     celix_long_hash_map_create_options_t opts = 
CELIX_EMPTY_LONG_HASH_MAP_CREATE_OPTIONS;
     return celix_longHashMap_createWithOptions(&opts);
 }
diff --git a/libs/utils/src/properties.c b/libs/utils/src/properties.c
index f48c1eb31..c1352a1be 100644
--- a/libs/utils/src/properties.c
+++ b/libs/utils/src/properties.c
@@ -297,7 +297,7 @@ static void celix_properties_removeEntryCallback(void* 
handle,
     celix_properties_destroyEntry(properties, entry);
 }
 
-celix_properties_t* celix_properties_create() {
+celix_properties_t* celix_properties_create(void) {
     celix_properties_t* props = malloc(sizeof(*props));
     if (props != NULL) {
         celix_string_hash_map_create_options_t opts = 
CELIX_EMPTY_STRING_HASH_MAP_CREATE_OPTIONS;
diff --git a/libs/utils/src/version.c b/libs/utils/src/version.c
index 0ef56d528..b114666a1 100644
--- a/libs/utils/src/version.c
+++ b/libs/utils/src/version.c
@@ -161,7 +161,7 @@ celix_status_t celix_version_tryParse(const char* 
versionStr, celix_version_t**
     return celix_version_parseInternal(versionStr, false, version);
 }
 
-celix_version_t* celix_version_createEmptyVersion() {
+celix_version_t* celix_version_createEmptyVersion(void) {
     return celix_version_create(0, 0, 0, NULL);
 }
 
diff --git a/libs/utils/src/version_range.c b/libs/utils/src/version_range.c
index 08e5d9c5d..22f9e9108 100644
--- a/libs/utils/src/version_range.c
+++ b/libs/utils/src/version_range.c
@@ -38,7 +38,7 @@ celix_version_range_t* 
celix_versionRange_createVersionRange(celix_version_t* lo
 }
 
 
-celix_version_range_t* celix_versionRange_createInfiniteVersionRange() {
+celix_version_range_t* celix_versionRange_createInfiniteVersionRange(void) {
     return 
celix_versionRange_createVersionRange(celix_version_createEmptyVersion(), true, 
NULL, true);
 }
 


Reply via email to