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

pnoltes pushed a commit to branch feature/674-add-element-type-to-array-list
in repository https://gitbox.apache.org/repos/asf/celix.git

commit 21f379de8a0ef8923e64453b851747add74ebdc6
Author: Pepijn Noltes <[email protected]>
AuthorDate: Sun Feb 4 19:07:44 2024 +0100

    #674 Add initial element type support for array list
---
 bundles/logging/log_admin/src/celix_log_admin.c |  14 +-
 libs/utils/gtest/src/ArrayListTestSuite.cc      |   2 +-
 libs/utils/include/celix_array_list.h           | 453 ++++++++++++++++++++---
 libs/utils/src/array_list.c                     | 465 ++++++++++++++++++++----
 libs/utils/src/array_list_private.h             |  41 ---
 5 files changed, 813 insertions(+), 162 deletions(-)

diff --git a/bundles/logging/log_admin/src/celix_log_admin.c 
b/bundles/logging/log_admin/src/celix_log_admin.c
index 5b983ef1..6b1be0f5 100644
--- a/bundles/logging/log_admin/src/celix_log_admin.c
+++ b/bundles/logging/log_admin/src/celix_log_admin.c
@@ -429,12 +429,12 @@ static size_t celix_logAdmin_setSinkEnabled(void *handle, 
const char* select, bo
 
 static celix_array_list_t* celix_logAdmin_currentLogServices(void *handle) {
     celix_log_admin_t* admin = handle;
-    celix_array_list_t* loggers = celix_arrayList_create();
+    celix_array_list_t* loggers = celix_arrayList_createStringArray();
     celixThreadRwlock_readLock(&admin->lock);
     hash_map_iterator_t iter = hashMapIterator_construct(admin->loggers);
     while (hashMapIterator_hasNext(&iter)) {
         celix_log_service_entry_t* visit = hashMapIterator_nextValue(&iter);
-        celix_arrayList_add(loggers, celix_utils_strdup(visit->name));
+        celix_arrayList_addString(loggers, visit->name);
     }
     celixThreadRwlock_unlock(&admin->lock);
     return loggers;
@@ -442,12 +442,12 @@ static celix_array_list_t* 
celix_logAdmin_currentLogServices(void *handle) {
 
 static celix_array_list_t* celix_logAdmin_currentSinks(void *handle) {
     celix_log_admin_t* admin = handle;
-    celix_array_list_t* sinks = celix_arrayList_create();
+    celix_array_list_t* sinks = celix_arrayList_createStringArray();
     celixThreadRwlock_readLock(&admin->lock);
     hash_map_iterator_t iter = hashMapIterator_construct(admin->sinks);
     while (hashMapIterator_hasNext(&iter)) {
         celix_log_sink_entry_t* entry = hashMapIterator_nextValue(&iter);
-        celix_arrayList_add(sinks, celix_utils_strdup(entry->name));
+        celix_arrayList_addString(sinks, entry->name);
     }
     celixThreadRwlock_unlock(&admin->lock);
     return sinks;
@@ -539,8 +539,8 @@ static void 
celix_logAdmin_setSinkEnabledCmd(celix_log_admin_t* admin, const cha
 static void celix_logAdmin_InfoCmd(celix_log_admin_t* admin, FILE* outStream, 
FILE* errorStream CELIX_UNUSED) {
     celix_array_list_t* logServices = celix_logAdmin_currentLogServices(admin);
     celix_array_list_t* sinks = celix_logAdmin_currentSinks(admin);
-    celix_arrayList_sort(logServices, (void*)strcmp);
-    celix_arrayList_sort(sinks, (void*)strcmp);
+    celix_arrayList_sort(logServices);
+    celix_arrayList_sort(sinks);
 
     fprintf(outStream, "Log Admin provided log services:\n");
     for (int i = 0 ; i < celix_arrayList_size(logServices); ++i) {
@@ -552,7 +552,6 @@ static void celix_logAdmin_InfoCmd(celix_log_admin_t* 
admin, FILE* outStream, FI
             fprintf(outStream, " |- %i) Log Service %20s, active log level %s, 
%s\n",
                     i+1, name, celix_logUtils_logLevelToString(level), 
detailed ? "detailed" : "brief");
         }
-        free(name);
     }
     celix_arrayList_destroy(logServices);
 
@@ -565,7 +564,6 @@ static void celix_logAdmin_InfoCmd(celix_log_admin_t* 
admin, FILE* outStream, FI
             if (found) {
                 fprintf(outStream, " |- %i) Log Sink %20s, %s\n", i+1, name, 
enabled ? "enabled" : "disabled");
             }
-            free(name);
         }
     } else {
         fprintf(outStream, "Log Admin has found 0 log sinks\n");
diff --git a/libs/utils/gtest/src/ArrayListTestSuite.cc 
b/libs/utils/gtest/src/ArrayListTestSuite.cc
index 5a0e60c3..488f069f 100644
--- a/libs/utils/gtest/src/ArrayListTestSuite.cc
+++ b/libs/utils/gtest/src/ArrayListTestSuite.cc
@@ -219,7 +219,7 @@ TEST_F(ArrayListTestSuite, TestSortForArrayList) {
     EXPECT_EQ(celix_arrayList_getInt(list, 3), 4);
 
 
-    celix_array_list_sort_entries_fp sort = [](celix_array_list_entry_t a, 
celix_array_list_entry_t b) -> int {
+    celix_array_list_compare_entries_fp sort = [](celix_array_list_entry_t a, 
celix_array_list_entry_t b) -> int {
         return a.intVal - b.intVal;
     };
     celix_arrayList_sortEntries(list, sort);
diff --git a/libs/utils/include/celix_array_list.h 
b/libs/utils/include/celix_array_list.h
index b38772b8..25925c89 100644
--- a/libs/utils/include/celix_array_list.h
+++ b/libs/utils/include/celix_array_list.h
@@ -22,6 +22,7 @@
 #include "celix_cleanup.h"
 #include "celix_errno.h"
 #include "celix_utils_export.h"
+#include "celix_version.h"
 
 #ifndef CELIX_ARRAY_LIST_H_
 #define CELIX_ARRAY_LIST_H_
@@ -40,36 +41,83 @@
 extern "C" {
 #endif
 
+/**
+ * @enum celix_array_list_element_type_t
+ * @brief An enumeration of the types of elements that can be stored in a 
Celix array list.
+ */
+typedef enum celix_array_list_element_type {
+    CELIX_ARRAY_LIST_ELEMENT_TYPE_UNDEFINED = 0, /**< Represents an undefined 
element type. */
+    CELIX_ARRAY_LIST_ELEMENT_TYPE_POINTER = 1,   /**< Represents a pointer 
element type. */
+    CELIX_ARRAY_LIST_ELEMENT_TYPE_STRING = 2, /**< Represents a string element 
type where the array list is the owner */
+    CELIX_ARRAY_LIST_ELEMENT_TYPE_STRING_REF =
+        3, /**< Represents a string element type where the array list is not 
the owner */
+    CELIX_ARRAY_LIST_ELEMENT_TYPE_INT = 4,    /**< Represents an integer 
element type. */
+    CELIX_ARRAY_LIST_ELEMENT_TYPE_LONG = 5,   /**< Represents a long integer 
element type. */
+    CELIX_ARRAY_LIST_ELEMENT_TYPE_UINT = 6,   /**< Represents an unsigned 
integer element type. */
+    CELIX_ARRAY_LIST_ELEMENT_TYPE_ULONG = 7,  /**< Represents an unsigned long 
integer element type. */
+    CELIX_ARRAY_LIST_ELEMENT_TYPE_FLOAT = 8,  /**< Represents a float element 
type. */
+    CELIX_ARRAY_LIST_ELEMENT_TYPE_DOUBLE = 9, /**< Represents a double element 
type. */
+    CELIX_ARRAY_LIST_ELEMENT_TYPE_BOOL = 10,  /**< Represents a boolean 
element type. */
+    CELIX_ARRAY_LIST_ELEMENT_TYPE_SIZE = 11,  /**< Represents a size_t element 
type. */
+    CELIX_ARRAY_LIST_ELEMENT_TYPE_VERSION = 12 /**< Represents a 
celix_version_t* element type. */
+} celix_array_list_element_type_t;
+
+/**
+ * @union celix_array_list_entry
+ * @brief A union representing an entry in a Celix array list.
+ *
+ * This union can hold different types of values, including pointers, strings, 
integers, long integers,
+ * unsigned integers, unsigned long integers, doubles, floats, booleans, and 
size_t values.
+ */
 typedef union celix_array_list_entry {
-    void *voidPtrVal;
-    int intVal;
-    long int longVal;
-    unsigned int uintVal;
-    unsigned long ulongVal;
-    double doubleVal;
-    float floatVal;
-    bool boolVal;
-    size_t sizeVal;
+    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. */
+    int intVal;            /**< An integer value when the element type is 
CELIX_ARRAY_LIST_ELEMENT_TYPE_INT  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. */
+    unsigned int uintVal;  /**< An unsigned integer value when the element 
type is CELIX_ARRAY_LIST_ELEMENT_TYPE_UINT or
+                              CELIX_ARRAY_LIST_ELEMENT_TYPE_UNDEFINED. */
+    unsigned long ulongVal; /**< An unsigned long integer value when the 
element type is
+                               CELIX_ARRAY_LIST_ELEMENT_TYPE_ULONG or 
CELIX_ARRAY_LIST_ELEMENT_TYPE_UNDEFINED. */
+    double doubleVal;       /**< A double value when the element type is 
CELIX_ARRAY_LIST_ELEMENT_TYPE_DOUBLE or
+                               CELIX_ARRAY_LIST_ELEMENT_TYPE_UNDEFINED. */
+    float floatVal;         /**< A float value when the element type is 
CELIX_ARRAY_LIST_ELEMENT_TYPE_FLOAT or
+                               CELIX_ARRAY_LIST_ELEMENT_TYPE_UNDEFINED. */
+    bool boolVal;           /**< A boolean value when the element type is 
CELIX_ARRAY_LIST_ELEMENT_TYPE_BOOL or
+                               CELIX_ARRAY_LIST_ELEMENT_TYPE_UNDEFINED. */
+    size_t sizeVal;         /**< A size_t value when the element type is 
CELIX_ARRAY_LIST_ELEMENT_TYPE_SIZE or
+                               CELIX_ARRAY_LIST_ELEMENT_TYPE_UNDEFINED. */
+    const celix_version_t* versionVal; /**< A celix_version_t* value when the 
element type is
+                                   CELIX_ARRAY_LIST_ELEMENT_TYPE_VERSION or 
CELIX_ARRAY_LIST_ELEMENT_TYPE_UNDEFINED. */
 } celix_array_list_entry_t;
 
+/**
+ * @brief A celix array list, which can store a list of undefined elements.
+ */
 typedef struct celix_array_list celix_array_list_t;
 
+/**
+ * @brief Equals function for array list entries, can be provided when 
creating a array list.
+ */
 typedef bool (*celix_arrayList_equals_fp)(celix_array_list_entry_t, 
celix_array_list_entry_t);
 
-typedef int (*celix_arrayList_sort_fp)(const void *, const void *);
-
 /**
  * @brief Compare function for array list entries, which can be used to sort a 
array list.
  */
 typedef int (*celix_array_list_compare_entries_fp)(celix_array_list_entry_t a, 
celix_array_list_entry_t b);
 
-typedef celix_array_list_compare_entries_fp celix_array_list_sort_entries_fp 
__attribute__((deprecated("Use celix_arrayList_compare_entries_fp instead")));
-
-
 /**
  * Additional create options when creating a array list.
  */
 typedef struct celix_array_list_create_options {
+    /**
+     * The element type of the array list. 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.
@@ -104,7 +152,12 @@ typedef struct celix_array_list_create_options {
     /**
      * Equals callback used when trying to find a array list entry.
      */
-    bool (*equalsCallback)(celix_array_list_entry_t a, 
celix_array_list_entry_t b) CELIX_OPTS_INIT;
+    celix_arrayList_equals_fp equalsCallback CELIX_OPTS_INIT;
+
+    /**
+     * Compare callback used when sorting the array list.
+     */
+     celix_array_list_compare_entries_fp compareCallback CELIX_OPTS_INIT;
 
 } celix_array_list_create_options_t;
 
@@ -112,30 +165,137 @@ typedef struct celix_array_list_create_options {
 /**
  * @brief C Macro to create a empty string_hash_map_create_options_t type.
  */
-#define CELIX_EMPTY_ARRAY_LIST_CREATE_OPTIONS {     \
-    .simpleRemovedCallback = NULL,                  \
-    .removedCallbackData = NULL,                    \
-    .removedCallback = NULL,                        \
-    .equalsCallback = NULL                          \
-}
+#define CELIX_EMPTY_ARRAY_LIST_CREATE_OPTIONS                                  
                                        \
+    {                                                                          
                                        \
+        .elementType = CELIX_ARRAY_LIST_ELEMENT_TYPE_UNDEFINED, 
.simpleRemovedCallback = NULL,                         \
+        .removedCallbackData = NULL, .removedCallback = NULL, .equalsCallback 
= NULL, .compareCallback = NULL          \
+    }
 #endif
 
 /**
- * @brief Creates a new empty array list.
+ * @brief Creates a new empty array list with an undefined element type.
+ *
+ * The remove, equals and compare callback will be NULL.
+ *
+ * @deprecated Use celix_arrayList_createWithOptions instead.
+ */
+CELIX_UTILS_DEPRECATED_EXPORT
+celix_array_list_t* celix_arrayList_create() __attribute__((deprecated("use 
create typed array list instead")));
+
+/**
+ * @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 and compare callback will be NULL.
+ */
+CELIX_UTILS_EXPORT
+celix_array_list_t* celix_arrayList_createPointerArray();
+
+/**
+ * @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, and equals and 
compare callback will be configured for
+ * string comparison.
+ */
+CELIX_UTILS_EXPORT
+celix_array_list_t* celix_arrayList_createStringArray();
+
+/**
+ * @brief Creates a new empty array list with a string element type where the 
array list is **not** the owner of the
+ * strings.
+ *
+ * The remove callback will be configured to NULL, and equals and compare 
callback will be configured for
+ * string comparison.
+ */
+CELIX_UTILS_EXPORT
+celix_array_list_t* celix_arrayList_createStringRefArray();
+
+/**
+ * @brief Creates a new empty array list with an integer element type.
+ *
+ * The remove callback will be configured to NULL, and equals and compare 
callback will be configured for
+ * integer comparison.
+ */
+CELIX_UTILS_EXPORT
+celix_array_list_t* celix_arrayList_createIntArray();
+
+/**
+ * @brief Creates a new empty array list with a long integer element type.
+ *
+ * The remove callback will be configured to NULL, and equals and compare 
callback will be configured for
+ * integer comparison.
+ */
+CELIX_UTILS_EXPORT
+celix_array_list_t* celix_arrayList_createLongArray();
+
+/**
+ * @brief Creates a new empty array list with an unsigned integer element type.
+ *
+ * The remove callback will be configured to NULL, and equals and compare 
callback will be configured for
+ * unsigned integer comparison.
+ */
+CELIX_UTILS_EXPORT
+celix_array_list_t* celix_arrayList_createUIntArray();
+
+/**
+ * @brief Creates a new empty array list with an unsigned long integer element 
type.
+ *
+ * The remove callback will be configured to NULL, and equals and compare 
callback will be configured for
+ * unsigned integer comparison.
  */
 CELIX_UTILS_EXPORT
-celix_array_list_t* celix_arrayList_create();
+celix_array_list_t* celix_arrayList_createULongArray();
 
 /**
- * @brief Creates a new empty array list, which uses the provided equals to 
check whether entries
- * are equal.
- * @deprecated This functions is deprecated, use 
celix_arrayList_createWithOptions instead.
+ * @brief Creates a new empty array list with a float element type.
+ *
+ * The remove callback will be configured to NULL, and equals and compare 
callback will be configured for
+ * float comparison.
+ */
+CELIX_UTILS_EXPORT
+celix_array_list_t* celix_arrayList_createFloatArray();
+
+/**
+ * @brief Creates a new empty array list with a double element type.
+ *
+ * The remove callback will be configured to NULL, and equals and compare 
callback will be configured for
+ * double comparison.
+ */
+CELIX_UTILS_EXPORT
+celix_array_list_t* celix_arrayList_createDoubleArray();
+
+/**
+ * @brief Creates a new empty array list with a boolean element type.
+ *
+ * The remove callback will be configured to NULL, and equals and compare 
callback will be configured for
+ * boolean comparison.
  */
 CELIX_UTILS_EXPORT
-celix_array_list_t* celix_arrayList_createWithEquals(celix_arrayList_equals_fp 
equals);
+celix_array_list_t* celix_arrayList_createBoolArray();
 
 /**
- * @brief Creates a new empty array listusing using the provided array list 
create options.
+ * @brief Creates a new empty array list with a size_t element type.
+ *
+ * The remove callback will be configured to NULL, and equals and compare 
callback will be configured for
+ * unsigned integer comparison.
+ */
+CELIX_UTILS_EXPORT
+celix_array_list_t* celix_arrayList_createSizeArray();
+
+/**
+ * @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, and equals 
and compare callback will be configured
+ * for celix version comparison.
+ */
+CELIX_UTILS_EXPORT
+celix_array_list_t* celix_arrayList_createVersionArray();
+
+/**
+ * @brief Creates a new empty array list using using the provided array list 
create options.
+ *
+ * The underlying element type will be undefined, until the first element is 
added.
+ *
  * @param opts The create options, only used during the creation of the array 
list.
  */
 CELIX_UTILS_EXPORT
@@ -160,6 +320,9 @@ 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
+ * CELIX_ARRAY_LIST_ELEMENT_TYPE_UNDEFINED.
+ *
  * @param map 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.
@@ -170,6 +333,22 @@ 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,
+ * CELIX_ARRAY_LIST_ELEMENT_TYPE_STRING_REF 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.
+ */
+CELIX_UTILS_EXPORT
+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_INT or
+ * CELIX_ARRAY_LIST_ELEMENT_TYPE_UNDEFINED.
+ *
  * @param map The array list.
  * @param index The entry index to return.
  * @return Returns the int value for the index. Returns 0 if index is out of 
bound.
@@ -180,6 +359,9 @@ int celix_arrayList_getInt(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
+ * CELIX_ARRAY_LIST_ELEMENT_TYPE_UNDEFINED.
+ *
  * @param map 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.
@@ -190,6 +372,9 @@ 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_UINT or
+ * CELIX_ARRAY_LIST_ELEMENT_TYPE_UNDEFINED.
+ *
  * @param map The array list.
  * @param index The entry index to return.
  * @return Returns the unsigned int value for the index. Returns 0 if index is 
out of bound.
@@ -200,6 +385,9 @@ unsigned int celix_arrayList_getUInt(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_ULONG or
+ * CELIX_ARRAY_LIST_ELEMENT_TYPE_UNDEFINED.
+ *
  * @param map The array list.
  * @param index The entry index to return.
  * @return Returns the unsigned long value for the index. Returns 0 if index 
is out of bound.
@@ -210,6 +398,9 @@ unsigned long int celix_arrayList_getULong(const 
celix_array_list_t *list, int i
 /**
  * @brief Returns the value for the provided index.
  *
+ * Can be used for array list with element type 
CELIX_ARRAY_LIST_ELEMENT_TYPE_FLOAT or
+ * CELIX_ARRAY_LIST_ELEMENT_TYPE_UNDEFINED.
+ *
  * @param map The array list.
  * @param index The entry index to return.
  * @return Returns the float value for the index. Returns 0 if index is out of 
bound.
@@ -220,6 +411,9 @@ float celix_arrayList_getFloat(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
+ * CELIX_ARRAY_LIST_ELEMENT_TYPE_UNDEFINED.
+ *
  * @param map 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.
@@ -230,6 +424,9 @@ 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
+ * CELIX_ARRAY_LIST_ELEMENT_TYPE_UNDEFINED.
+ *
  * @param map 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.
@@ -240,6 +437,9 @@ 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_SIZE or
+ * CELIX_ARRAY_LIST_ELEMENT_TYPE_UNDEFINED.
+ *
  * @param map The array list.
  * @param index The entry index to return.
  * @return Returns the size_t value for the index. Returns 0 if index is out 
of bound.
@@ -247,95 +447,197 @@ bool celix_arrayList_getBool(const celix_array_list_t 
*list, int index);
 CELIX_UTILS_EXPORT
 size_t celix_arrayList_getSize(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,
+ * 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.
+ */
+CELIX_UTILS_EXPORT
+const celix_version_t* celix_arrayList_getVersion(const celix_array_list_t 
*list, int index);
+
 /**
  * @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_POINTER or
+ * CELIX_ARRAY_LIST_ELEMENT_TYPE_UNDEFINED.
+ *
  * @param map The array list.
  * @param value The pointer value to add to the array list.
  * @return CELIX_SUCCESS if the value is added, CELIX_ENOMEM if the array list 
is out of memory.
  */
 CELIX_UTILS_EXPORT
-celix_status_t celix_arrayList_add(celix_array_list_t *list, void* value);
+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,
+ * CELIX_ARRAY_LIST_ELEMENT_TYPE_STRING_REF 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
+ * if the array list element type is CELIX_ARRAY_LIST_ELEMENT_TYPE_STRING_REF 
or
+ * CELIX_ARRAY_LIST_ELEMENT_TYPE_UNDEFINED, the string will be added as 
reference (as-is).
+ *
+ * @param list The array list.
+ * @param value The string value to add to the array list.
+ * @return CELIX_SUCCESS if the value is added, CELIX_ENOMEM if the array list 
is out of memory.
+ */
+CELIX_UTILS_EXPORT
+celix_status_t celix_arrayList_addString(celix_array_list_t* list, const char* 
value);
+
+/**
+ * @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.
+ *
+ * Can only be used for array list with element type 
CELIX_ARRAY_LIST_ELEMENT_TYPE_STRING.
+ *
+ * @param list The array list.
+ * @param value The string value to add to the array list.
+ * @return CELIX_SUCCESS if the value is added, CELIX_ENOMEM if the array list 
is out of memory.
+ */
+CELIX_UTILS_EXPORT
+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_INT or
+ * CELIX_ARRAY_LIST_ELEMENT_TYPE_UNDEFINED.
+ *
  * @param map The array list.
  * @param value The int value to add to the array list.
  * @return CELIX_SUCCESS if the value is added, CELIX_ENOMEM if the array list 
is out of memory.
  */
 CELIX_UTILS_EXPORT
-celix_status_t celix_arrayList_addInt(celix_array_list_t *list, int value);
+celix_status_t celix_arrayList_addInt(celix_array_list_t* list, int 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
+ * CELIX_ARRAY_LIST_ELEMENT_TYPE_UNDEFINED.
+ *
  * @param map The array list.
  * @param value The long value to add to the array list.
  * @return CELIX_SUCCESS if the value is added, CELIX_ENOMEM if the array list 
is out of memory.
  */
 CELIX_UTILS_EXPORT
-celix_status_t celix_arrayList_addLong(celix_array_list_t *list, long value);
+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_UINT or
+ * CELIX_ARRAY_LIST_ELEMENT_TYPE_UNDEFINED.
+ *
  * @param map The array list.
  * @param value The unsigned int value to add to the array list.
  * @return CELIX_SUCCESS if the value is added, CELIX_ENOMEM if the array list 
is out of memory.
  */
 CELIX_UTILS_EXPORT
-celix_status_t celix_arrayList_addUInt(celix_array_list_t *list, unsigned int 
value);
+celix_status_t celix_arrayList_addUInt(celix_array_list_t* list, unsigned int 
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_ULONG or
+ * CELIX_ARRAY_LIST_ELEMENT_TYPE_UNDEFINED.
+ *
  * @param map The array list.
  * @param value The unsigned long value to add to the array list.
  * @return CELIX_SUCCESS if the value is added, CELIX_ENOMEM if the array list 
is out of memory.
  */
 CELIX_UTILS_EXPORT
-celix_status_t celix_arrayList_addULong(celix_array_list_t *list, unsigned 
long value);
+celix_status_t celix_arrayList_addULong(celix_array_list_t* list, unsigned 
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_FLOAT or
+ * CELIX_ARRAY_LIST_ELEMENT_TYPE_UNDEFINED.
+ *
  * @param map The array list.
  * @param value The float value to add to the array list.
  * @return CELIX_SUCCESS if the value is added, CELIX_ENOMEM if the array list 
is out of memory.
  */
 CELIX_UTILS_EXPORT
-celix_status_t celix_arrayList_addFloat(celix_array_list_t *list, float value);
+celix_status_t celix_arrayList_addFloat(celix_array_list_t* list, float 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
+ * CELIX_ARRAY_LIST_ELEMENT_TYPE_UNDEFINED.
+ *
  * @param map The array list.
  * @param value The double value to add to the array list.
  * @return CELIX_SUCCESS if the value is added, CELIX_ENOMEM if the array list 
is out of memory.
  */
 CELIX_UTILS_EXPORT
-celix_status_t celix_arrayList_addDouble(celix_array_list_t *list, double 
value);
+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
+ * CELIX_ARRAY_LIST_ELEMENT_TYPE_UNDEFINED.
+ *
  * @param map The array list.
  * @param value The bool value to add to the array list.
  * @return CELIX_SUCCESS if the value is added, CELIX_ENOMEM if the array list 
is out of memory.
  */
 CELIX_UTILS_EXPORT
-celix_status_t celix_arrayList_addBool(celix_array_list_t *list, bool value);
+celix_status_t celix_arrayList_addBool(celix_array_list_t* list, bool 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_SIZE or
+ * CELIX_ARRAY_LIST_ELEMENT_TYPE_UNDEFINED.
+ *
  * @param map The array list.
  * @param value The size_t value to add to the array list.
  * @return CELIX_SUCCESS if the value is added, CELIX_ENOMEM if the array list 
is out of memory.
  */
 CELIX_UTILS_EXPORT
-celix_status_t celix_arrayList_addSize(celix_array_list_t *list, size_t value);
+celix_status_t celix_arrayList_addSize(celix_array_list_t* list, size_t 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,
+ * 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
+ * if the array list element type is CELIX_ARRAY_LIST_ELEMENT_TYPE_UNDEFINED,
+ * the string will be added as reference (as-is).
+ *
+ * @param list The array list.
+ * @param value The version value to add to the array list.
+ * @return CELIX_SUCCESS if the value is added, CELIX_ENOMEM if the array list 
is out of memory.
+ */
+CELIX_UTILS_EXPORT
+celix_status_t celix_arrayList_addVersion(celix_array_list_t* list, const 
celix_version_t* value);
+
+/**
+ * @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.
+ *
+ *
+ * @param list The array list.
+ * @param value The version value to add to the array list.
+ * @return CELIX_SUCCESS if the value is added, CELIX_ENOMEM if the array list 
is out of memory.
+ */
+CELIX_UTILS_EXPORT
+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.
@@ -383,83 +685,134 @@ void celix_arrayList_removeEntry(celix_array_list_t 
*list, celix_array_list_entr
 /**
  * @brief Remove the first pointer entry from array list which matches the 
provided value.
  *
+ * Can be used for array list with 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.
+ */
+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.
+ *
+ * Can be used for array list with element type 
CELIX_ARRAY_LIST_ELEMENT_TYPE_STRING,
+ * CELIX_ARRAY_LIST_ELEMENT_TYPE_STRING_REF 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.
  */
 CELIX_UTILS_EXPORT
-void celix_arrayList_remove(celix_array_list_t *list, void *value);
+void celix_arrayList_removeString(celix_array_list_t* list, const char* value);
 
 /**
  * @brief Remove the first int entry from array list which matches the 
provided value.
  *
+ * Can be used for array list with element type 
CELIX_ARRAY_LIST_ELEMENT_TYPE_INT 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.
  */
 CELIX_UTILS_EXPORT
-void celix_arrayList_removeInt(celix_array_list_t *list, int value);
+void celix_arrayList_removeInt(celix_array_list_t* list, int value);
 
 /**
  * @brief Remove the first long entry from array list which matches the 
provided value.
  *
+ * Can be used for 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.
  */
 CELIX_UTILS_EXPORT
-void celix_arrayList_removeLong(celix_array_list_t *list, long value);
+void celix_arrayList_removeLong(celix_array_list_t* list, long value);
 
 /**
  * @brief Remove the first unsigned int entry from array list which matches 
the provided value.
  *
+ * Can be used for array list with element type 
CELIX_ARRAY_LIST_ELEMENT_TYPE_UINT 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.
  */
 CELIX_UTILS_EXPORT
-void celix_arrayList_removeUInt(celix_array_list_t *list, unsigned int value);
+void celix_arrayList_removeUInt(celix_array_list_t* list, unsigned int value);
 
 /**
  * @brief Remove the first unsigned long entry from array list which matches 
the provided value.
  *
+ * Can be used for array list with element type 
CELIX_ARRAY_LIST_ELEMENT_TYPE_ULONG 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.
  */
 CELIX_UTILS_EXPORT
-void celix_arrayList_removeULong(celix_array_list_t *list, unsigned long 
value);
+void celix_arrayList_removeULong(celix_array_list_t* list, unsigned long 
value);
 
 /**
  * @brief Remove the first float entry from array list which matches the 
provided value.
  *
+ * Can be used for array list with element type 
CELIX_ARRAY_LIST_ELEMENT_TYPE_FLOAT 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.
  */
 CELIX_UTILS_EXPORT
-void celix_arrayList_removeFloat(celix_array_list_t *list, float value);
+void celix_arrayList_removeFloat(celix_array_list_t* list, float value);
 
 /**
  * @brief Remove the first double entry from array list which matches the 
provided value.
  *
+ * Can be used for array list with 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.
  */
 CELIX_UTILS_EXPORT
-void celix_arrayList_removeDouble(celix_array_list_t *list, double value);
+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.
  *
+ * Can be used for array list with 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.
  */
 CELIX_UTILS_EXPORT
-void celix_arrayList_removeBool(celix_array_list_t *list, bool value);
+void celix_arrayList_removeBool(celix_array_list_t* list, bool value);
 
 /**
  * @brief Remove the first size entry from array list which matches the 
provided value.
  *
+ * Can be used for array list with element type 
CELIX_ARRAY_LIST_ELEMENT_TYPE_SIZE 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.
  */
 CELIX_UTILS_EXPORT
-void celix_arrayList_removeSize(celix_array_list_t *list, size_t value);
+void celix_arrayList_removeSize(celix_array_list_t* list, size_t value);
+
+/**
+ * @brief Remove the first version entry from array list which matches the 
provided value.
+ *
+ * Can be used for array list with 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.
+ */
+CELIX_UTILS_EXPORT
+void celix_arrayList_removeVersion(celix_array_list_t* list, const 
celix_version_t* value);
 
 /**
  * @brief Sort the array list using the provided sort function.
@@ -468,11 +821,11 @@ CELIX_UTILS_EXPORT
 void celix_arrayList_sortEntries(celix_array_list_t *list, 
celix_array_list_compare_entries_fp compare);
 
 /**
- * @warning Never use this function with array of doubles, since on some 
32-bit platform (sizeof(double)==8 && sizeof(void*)==4)
- * @deprecated This function is deprecated, use celix_arrayList_sortEntries 
instead.
+ * @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.
  */
-CELIX_UTILS_DEPRECATED_EXPORT
-void celix_arrayList_sort(celix_array_list_t *list, celix_arrayList_sort_fp 
sortFp);
+CELIX_UTILS_EXPORT
+void celix_arrayList_sort(celix_array_list_t *list);
 
 #ifdef __cplusplus
 }
diff --git a/libs/utils/src/array_list.c b/libs/utils/src/array_list.c
index 5b7a16e2..807d21b2 100644
--- a/libs/utils/src/array_list.c
+++ b/libs/utils/src/array_list.c
@@ -24,26 +24,135 @@
  *  \copyright  Apache License, Version 2.0
  */
 
-#include <stdlib.h>
+#include <assert.h>
+#include <stdint.h>
 #include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
 
 #include "celix_array_list.h"
-#include "array_list_private.h"
 #include "celix_build_assert.h"
-
-static bool celix_arrayList_defaultEquals(celix_array_list_entry_t a, 
celix_array_list_entry_t b) {
+#include "celix_err.h"
+#include "celix_stdlib_cleanup.h"
+#include "celix_utils.h"
+
+struct celix_array_list {
+    celix_array_list_element_type_t elementType;
+    celix_array_list_entry_t* elementData;
+    size_t size;
+    size_t capacity;
+    unsigned int modCount;
+    celix_arrayList_equals_fp  equalsCallback;
+    celix_array_list_compare_entries_fp compareCallback;
+    void (*simpleRemovedCallback)(void* value);
+    void* removedCallbackData;
+    void (*removedCallback)(void* data, celix_array_list_entry_t entry);
+};
+
+static bool celix_arrayList_undefinedEquals(celix_array_list_entry_t a, 
celix_array_list_entry_t b) {
     return memcmp(&a, &b, sizeof(a)) == 0;
 }
 
+static int celix_arrayList_comparePtrEntries(celix_array_list_entry_t a, 
celix_array_list_entry_t b) {
+     uintptr_t ptrA = (uintptr_t)a.voidPtrVal;
+     uintptr_t ptrB = (uintptr_t)b.voidPtrVal;
+    return (int)(ptrA - ptrB);
+}
+
+static bool celix_arrayList_PtrEquals(celix_array_list_entry_t a, 
celix_array_list_entry_t b) {
+    return celix_arrayList_comparePtrEntries(a, b) == 0;
+}
+
+static int celix_arrayList_compareStringEntries(celix_array_list_entry_t a, 
celix_array_list_entry_t b) {
+    return strcmp(a.stringVal, b.stringVal);
+}
+
+static bool celix_arrayList_stringEquals(celix_array_list_entry_t a, 
celix_array_list_entry_t b) {
+    return celix_arrayList_compareStringEntries(a, b) == 0;
+}
+
+static int celix_arrayList_compareIntEntries(celix_array_list_entry_t a, 
celix_array_list_entry_t b) {
+    return a.intVal - b.intVal;
+}
+
+static bool celix_arrayList_intEquals(celix_array_list_entry_t a, 
celix_array_list_entry_t b) {
+    return celix_arrayList_compareIntEntries(a, b) == 0;
+}
+
+static int celix_arrayList_compareLongEntries(celix_array_list_entry_t a, 
celix_array_list_entry_t b) {
+    return a.longVal > b.longVal ? 1 : (a.longVal < b.longVal ? -1 : 0);
+}
+
+static bool celix_arrayList_longEquals(celix_array_list_entry_t a, 
celix_array_list_entry_t b) {
+    return celix_arrayList_compareLongEntries(a, b) == 0;
+}
+
+static int celix_arrayList_compareUIntEntries(celix_array_list_entry_t a, 
celix_array_list_entry_t b) {
+    return a.uintVal > b.uintVal ? 1 : (a.uintVal < b.uintVal ? -1 : 0);
+}
+
+static bool celix_arrayList_uintEquals(celix_array_list_entry_t a, 
celix_array_list_entry_t b) {
+    return celix_arrayList_compareUIntEntries(a, b) == 0;
+}
+
+static int celix_arrayList_compareULongEntries(celix_array_list_entry_t a, 
celix_array_list_entry_t b) {
+    return a.ulongVal > b.ulongVal ? 1 : (a.ulongVal < b.ulongVal ? -1 : 0);
+}
+
+static bool celix_arrayList_ulongEquals(celix_array_list_entry_t a, 
celix_array_list_entry_t b) {
+    return celix_arrayList_compareULongEntries(a, b) == 0;
+}
+
+static int celix_arrayList_compareFloatEntries(celix_array_list_entry_t a, 
celix_array_list_entry_t b) {
+    return a.floatVal > b.floatVal ? 1 : (a.floatVal < b.floatVal ? -1 : 0);
+}
+
+static bool celix_arrayList_floatEquals(celix_array_list_entry_t a, 
celix_array_list_entry_t b) {
+    return celix_arrayList_compareFloatEntries(a, b) == 0;
+}
+
+static int celix_arrayList_compareDoubleEntries(celix_array_list_entry_t a, 
celix_array_list_entry_t b) {
+    return a.doubleVal > b.doubleVal ? 1 : (a.doubleVal < b.doubleVal ? -1 : 
0);
+}
+
+static bool celix_arrayList_doubleEquals(celix_array_list_entry_t a, 
celix_array_list_entry_t b) {
+    return celix_arrayList_compareDoubleEntries(a, b) == 0;
+}
+
+static int celix_arrayList_compareBoolEntries(celix_array_list_entry_t a, 
celix_array_list_entry_t b) {
+    return a.boolVal - b.boolVal;
+}
+
+static bool celix_arrayList_boolEquals(celix_array_list_entry_t a, 
celix_array_list_entry_t b) {
+    return celix_arrayList_compareBoolEntries(a, b) == 0;
+}
+
+static int celix_arrayList_compareSizeEntries(celix_array_list_entry_t a, 
celix_array_list_entry_t b) {
+    return a.sizeVal > b.sizeVal ? 1 : (a.sizeVal < b.sizeVal ? -1 : 0);
+}
+
+static bool celix_arrayList_sizeEquals(celix_array_list_entry_t a, 
celix_array_list_entry_t b) {
+    return celix_arrayList_compareSizeEntries(a, b) == 0;
+}
+
+static int celix_arrayList_compareVersionEntries(celix_array_list_entry_t a, 
celix_array_list_entry_t b) {
+    return celix_version_compareTo(a.versionVal, b.versionVal);
+}
+
+static bool celix_arrayList_versionEquals(celix_array_list_entry_t a, 
celix_array_list_entry_t b) {
+    return celix_arrayList_compareVersionEntries(a, b) == 0;
+}
+
 static bool celix_arrayList_equalsForElement(celix_array_list_t *list, 
celix_array_list_entry_t a, celix_array_list_entry_t b) {
-    bool equals = false;
-    if (list != NULL) {
-        if (list->equals != NULL) {
-            equals = list->equals(a, b);
-        }
+    if (list && list->equalsCallback != NULL) {
+        return list->equalsCallback(a, b);
     }
-    return equals;
+    return false;
+}
+
+static void celix_arrayList_destroyVersion(void* v) {
+    celix_version_t* version = v;
+    celix_version_destroy(version);
 }
 
 static void celix_arrayList_callRemovedCallback(celix_array_list_t *list, int 
index) {
@@ -75,24 +184,139 @@ static celix_status_t 
celix_arrayList_ensureCapacity(celix_array_list_t* list, i
     return status;
 }
 
+static void celix_arrayList_setTypeSpecificCallbacks(celix_array_list_t* list) 
{
+    switch (list->elementType) {
+    case CELIX_ARRAY_LIST_ELEMENT_TYPE_POINTER:
+        list->equalsCallback = celix_arrayList_PtrEquals;
+        list->compareCallback = celix_arrayList_comparePtrEntries;
+        break;
+    case CELIX_ARRAY_LIST_ELEMENT_TYPE_STRING:
+        list->simpleRemovedCallback = free;
+        list->equalsCallback = celix_arrayList_stringEquals;
+        list->compareCallback = celix_arrayList_compareStringEntries;
+        break;
+    case CELIX_ARRAY_LIST_ELEMENT_TYPE_INT:
+        list->equalsCallback = celix_arrayList_intEquals;
+        list->compareCallback = celix_arrayList_compareIntEntries;
+        break;
+    case CELIX_ARRAY_LIST_ELEMENT_TYPE_LONG:
+        list->equalsCallback = celix_arrayList_longEquals;
+        list->compareCallback = celix_arrayList_compareLongEntries;
+        break;
+    case CELIX_ARRAY_LIST_ELEMENT_TYPE_UINT:
+        list->equalsCallback = celix_arrayList_uintEquals;
+        list->compareCallback = celix_arrayList_compareUIntEntries;
+        break;
+    case CELIX_ARRAY_LIST_ELEMENT_TYPE_ULONG:
+        list->equalsCallback = celix_arrayList_ulongEquals;
+        list->compareCallback = celix_arrayList_compareULongEntries;
+        break;
+    case CELIX_ARRAY_LIST_ELEMENT_TYPE_FLOAT:
+        list->equalsCallback = celix_arrayList_floatEquals;
+        list->compareCallback = celix_arrayList_compareFloatEntries;
+        break;
+    case CELIX_ARRAY_LIST_ELEMENT_TYPE_DOUBLE:
+        list->equalsCallback = celix_arrayList_doubleEquals;
+        list->compareCallback = celix_arrayList_compareDoubleEntries;
+        break;
+    case CELIX_ARRAY_LIST_ELEMENT_TYPE_BOOL:
+        list->equalsCallback = celix_arrayList_boolEquals;
+        list->compareCallback = celix_arrayList_compareBoolEntries;
+        break;
+    case CELIX_ARRAY_LIST_ELEMENT_TYPE_SIZE:
+        list->equalsCallback = celix_arrayList_sizeEquals;
+        list->compareCallback = celix_arrayList_compareSizeEntries;
+        break;
+    case CELIX_ARRAY_LIST_ELEMENT_TYPE_VERSION:
+        list->simpleRemovedCallback = celix_arrayList_destroyVersion;
+        list->equalsCallback = celix_arrayList_versionEquals;
+        list->compareCallback = celix_arrayList_compareVersionEntries;
+        break;
+    default:
+        assert(list->elementType == CELIX_ARRAY_LIST_ELEMENT_TYPE_UNDEFINED);
+        list->equalsCallback = celix_arrayList_undefinedEquals;
+        break;
+    }
+}
+
 celix_array_list_t* celix_arrayList_createWithOptions(const 
celix_array_list_create_options_t* opts) {
-    celix_array_list_t *list = calloc(1, sizeof(*list));
-    if (list != NULL) {
+    celix_autofree celix_array_list_t *list = calloc(1, sizeof(*list));
+    if (list) {
         list->capacity = 10;
         list->elementData = malloc(sizeof(celix_array_list_entry_t) * 
list->capacity);
-        list->equals = opts->equalsCallback == NULL ? 
celix_arrayList_defaultEquals : opts->equalsCallback;
-        list->simpleRemovedCallback = opts->simpleRemovedCallback;
-        list->removedCallbackData = opts->removedCallbackData;
-        list->removedCallback = opts->removedCallback;
+        if (!list->elementData) {
+            celix_err_push("Failed to allocate memory for elementData");
+            return NULL;
+        }
+
+        list->elementType = opts->elementType;
+        celix_arrayList_setTypeSpecificCallbacks(list);
+
+        if (opts->simpleRemovedCallback) {
+            list->simpleRemovedCallback = opts->simpleRemovedCallback;
+        }
+        if (opts->removedCallback) {
+            list->removedCallback = opts->removedCallback;
+            list->removedCallbackData = opts->removedCallbackData;
+        }
     }
-    return list;
+    return celix_steal_ptr(list);
 }
 
-celix_array_list_t* celix_arrayList_create() {
+static celix_array_list_t* 
celix_arrayList_createTypedArray(celix_array_list_element_type_t type) {
     celix_array_list_create_options_t opts = 
CELIX_EMPTY_ARRAY_LIST_CREATE_OPTIONS;
+    opts.elementType = type;
     return celix_arrayList_createWithOptions(&opts);
 }
 
+celix_array_list_t* celix_arrayList_create() {
+    return 
celix_arrayList_createTypedArray(CELIX_ARRAY_LIST_ELEMENT_TYPE_UNDEFINED);
+}
+
+celix_array_list_t* celix_arrayList_createPointerArray() {
+    return 
celix_arrayList_createTypedArray(CELIX_ARRAY_LIST_ELEMENT_TYPE_POINTER);
+}
+
+celix_array_list_t* celix_arrayList_createStringArray() {
+    return 
celix_arrayList_createTypedArray(CELIX_ARRAY_LIST_ELEMENT_TYPE_STRING);
+}
+
+celix_array_list_t* celix_arrayList_createStringRefArray() {
+    return 
celix_arrayList_createTypedArray(CELIX_ARRAY_LIST_ELEMENT_TYPE_STRING_REF);
+}
+
+celix_array_list_t* celix_arrayList_createIntArray() {
+    return celix_arrayList_createTypedArray(CELIX_ARRAY_LIST_ELEMENT_TYPE_INT);
+}
+
+celix_array_list_t* celix_arrayList_createLongArray() {
+    return 
celix_arrayList_createTypedArray(CELIX_ARRAY_LIST_ELEMENT_TYPE_LONG);
+}
+
+celix_array_list_t* celix_arrayList_createUIntArray() {
+    return 
celix_arrayList_createTypedArray(CELIX_ARRAY_LIST_ELEMENT_TYPE_UINT);
+}
+
+celix_array_list_t* celix_arrayList_createULongArray() {
+    return 
celix_arrayList_createTypedArray(CELIX_ARRAY_LIST_ELEMENT_TYPE_ULONG);
+}
+
+celix_array_list_t* celix_arrayList_createFloatArray() {
+    return 
celix_arrayList_createTypedArray(CELIX_ARRAY_LIST_ELEMENT_TYPE_FLOAT);
+}
+
+celix_array_list_t* celix_arrayList_createDoubleArray() {
+    return 
celix_arrayList_createTypedArray(CELIX_ARRAY_LIST_ELEMENT_TYPE_DOUBLE);
+}
+
+celix_array_list_t* celix_arrayList_createBoolArray() {
+    return 
celix_arrayList_createTypedArray(CELIX_ARRAY_LIST_ELEMENT_TYPE_BOOL);
+}
+
+celix_array_list_t* celix_arrayList_createSizeArray() {
+    return 
celix_arrayList_createTypedArray(CELIX_ARRAY_LIST_ELEMENT_TYPE_SIZE);
+}
+
 celix_array_list_t* celix_arrayList_createWithEquals(celix_arrayList_equals_fp 
equals) {
     celix_array_list_create_options_t opts = 
CELIX_EMPTY_ARRAY_LIST_CREATE_OPTIONS;
     opts.equalsCallback = equals;
@@ -108,7 +332,7 @@ void celix_arrayList_destroy(celix_array_list_t *list) {
 }
 
 int celix_arrayList_size(const celix_array_list_t *list) {
-    return list->size;
+    return (int)list->size;
 }
 
 static celix_array_list_entry_t arrayList_getEntry(const celix_array_list_t 
*list, int index) {
@@ -120,41 +344,73 @@ static celix_array_list_entry_t arrayList_getEntry(const 
celix_array_list_t *lis
     return entry;
 }
 
-void* celix_arrayList_get(const celix_array_list_t *list, int index) {
+void* celix_arrayList_get(const celix_array_list_t* list, int index) {
+    assert(list->elementType == CELIX_ARRAY_LIST_ELEMENT_TYPE_POINTER ||
+           list->elementType == CELIX_ARRAY_LIST_ELEMENT_TYPE_UNDEFINED);
     return arrayList_getEntry(list, index).voidPtrVal;
 }
 
-int celix_arrayList_getInt(const celix_array_list_t* list, int index) { return 
arrayList_getEntry(list, index).intVal; }
+const char* celix_arrayList_getString(const celix_array_list_t* list, int 
index) {
+    assert(list->elementType == CELIX_ARRAY_LIST_ELEMENT_TYPE_STRING ||
+           list->elementType == CELIX_ARRAY_LIST_ELEMENT_TYPE_STRING_REF ||
+           list->elementType == CELIX_ARRAY_LIST_ELEMENT_TYPE_UNDEFINED);
+    return arrayList_getEntry(list, index).stringVal;
+}
+
+int celix_arrayList_getInt(const celix_array_list_t* list, int index) {
+    assert(list->elementType == CELIX_ARRAY_LIST_ELEMENT_TYPE_INT ||
+           list->elementType == CELIX_ARRAY_LIST_ELEMENT_TYPE_UNDEFINED);
+    return arrayList_getEntry(list, index).intVal;
+}
 
 long int celix_arrayList_getLong(const celix_array_list_t* list, int index) {
+    assert(list->elementType == CELIX_ARRAY_LIST_ELEMENT_TYPE_LONG ||
+           list->elementType == CELIX_ARRAY_LIST_ELEMENT_TYPE_UNDEFINED);
     return arrayList_getEntry(list, index).longVal;
 }
 
 unsigned int celix_arrayList_getUInt(const celix_array_list_t* list, int 
index) {
+    assert(list->elementType == CELIX_ARRAY_LIST_ELEMENT_TYPE_UINT ||
+           list->elementType == CELIX_ARRAY_LIST_ELEMENT_TYPE_UNDEFINED);
     return arrayList_getEntry(list, index).uintVal;
 }
 
 unsigned long int celix_arrayList_getULong(const celix_array_list_t* list, int 
index) {
+    assert(list->elementType == CELIX_ARRAY_LIST_ELEMENT_TYPE_ULONG ||
+           list->elementType == CELIX_ARRAY_LIST_ELEMENT_TYPE_UNDEFINED);
     return arrayList_getEntry(list, index).ulongVal;
 }
 
 float celix_arrayList_getFloat(const celix_array_list_t* list, int index) {
+    assert(list->elementType == CELIX_ARRAY_LIST_ELEMENT_TYPE_FLOAT ||
+           list->elementType == CELIX_ARRAY_LIST_ELEMENT_TYPE_UNDEFINED);
     return arrayList_getEntry(list, index).floatVal;
 }
 
 double celix_arrayList_getDouble(const celix_array_list_t* list, int index) {
+    assert(list->elementType == CELIX_ARRAY_LIST_ELEMENT_TYPE_DOUBLE ||
+           list->elementType == CELIX_ARRAY_LIST_ELEMENT_TYPE_UNDEFINED);
     return arrayList_getEntry(list, index).doubleVal;
 }
 
 bool celix_arrayList_getBool(const celix_array_list_t* list, int index) {
+    assert(list->elementType == CELIX_ARRAY_LIST_ELEMENT_TYPE_BOOL ||
+           list->elementType == CELIX_ARRAY_LIST_ELEMENT_TYPE_UNDEFINED);
     return arrayList_getEntry(list, index).boolVal;
 }
 
 size_t celix_arrayList_getSize(const celix_array_list_t* list, int index) {
+    assert(list->elementType == CELIX_ARRAY_LIST_ELEMENT_TYPE_SIZE ||
+           list->elementType == CELIX_ARRAY_LIST_ELEMENT_TYPE_UNDEFINED);
     return arrayList_getEntry(list, index).sizeVal;
 }
 
-static celix_status_t celix_arrayList_addEntry(celix_array_list_t *list, 
celix_array_list_entry_t entry) {
+const celix_version_t* celix_arrayList_getVersion(const celix_array_list_t* 
list, int index) {
+    assert(list->elementType == CELIX_ARRAY_LIST_ELEMENT_TYPE_VERSION);
+    return arrayList_getEntry(list, index).versionVal;
+}
+
+static celix_status_t celix_arrayList_addEntry(celix_array_list_t* list, 
celix_array_list_entry_t entry) {
     celix_status_t status = celix_arrayList_ensureCapacity(list, 
(int)list->size + 1);
     if (status == CELIX_SUCCESS) {
         list->elementData[list->size++] = entry;
@@ -162,69 +418,139 @@ static celix_status_t 
celix_arrayList_addEntry(celix_array_list_t *list, celix_a
     return status;
 }
 
-celix_status_t celix_arrayList_add(celix_array_list_t *list, void * element) {
+celix_status_t celix_arrayList_add(celix_array_list_t* list, void* element) {
+    assert(list->elementType == CELIX_ARRAY_LIST_ELEMENT_TYPE_POINTER ||
+           list->elementType == CELIX_ARRAY_LIST_ELEMENT_TYPE_UNDEFINED);
     celix_array_list_entry_t entry;
     memset(&entry, 0, sizeof(entry));
     entry.voidPtrVal = element;
     return celix_arrayList_addEntry(list, entry);
 }
 
-celix_status_t celix_arrayList_addInt(celix_array_list_t *list, int val) {
+celix_status_t celix_arrayList_addString(celix_array_list_t* list, const char* 
val) {
+    assert(list->elementType == CELIX_ARRAY_LIST_ELEMENT_TYPE_STRING ||
+           list->elementType == CELIX_ARRAY_LIST_ELEMENT_TYPE_STRING_REF ||
+           list->elementType == CELIX_ARRAY_LIST_ELEMENT_TYPE_UNDEFINED);
+    celix_array_list_entry_t entry;
+    memset(&entry, 0, sizeof(entry));
+    if (list->elementType == CELIX_ARRAY_LIST_ELEMENT_TYPE_STRING) {
+        entry.stringVal = celix_utils_strdup(val);
+        if (entry.stringVal == NULL) {
+            return CELIX_ENOMEM;
+        }
+    } else {
+        entry.stringVal = val;
+    }
+    return celix_arrayList_addEntry(list, entry);
+}
+
+celix_status_t celix_arrayList_assignString(celix_array_list_t* list, char* 
value) {
+    assert(list->elementType == CELIX_ARRAY_LIST_ELEMENT_TYPE_STRING);
+    celix_array_list_entry_t entry;
+    memset(&entry, 0, sizeof(entry));
+    entry.stringVal = celix_utils_strdup(value);
+    if (entry.stringVal == NULL) {
+        return CELIX_ENOMEM;
+    }
+    return celix_arrayList_addEntry(list, entry);
+}
+
+celix_status_t celix_arrayList_addInt(celix_array_list_t* list, int val) {
+    assert(list->elementType == CELIX_ARRAY_LIST_ELEMENT_TYPE_INT ||
+           list->elementType == CELIX_ARRAY_LIST_ELEMENT_TYPE_UNDEFINED);
     celix_array_list_entry_t entry;
     memset(&entry, 0, sizeof(entry));
     entry.intVal = val;
     return celix_arrayList_addEntry(list, entry);
 }
 
-celix_status_t celix_arrayList_addLong(celix_array_list_t *list, long val) {
+celix_status_t celix_arrayList_addLong(celix_array_list_t* list, long val) {
+    assert(list->elementType == CELIX_ARRAY_LIST_ELEMENT_TYPE_LONG ||
+           list->elementType == CELIX_ARRAY_LIST_ELEMENT_TYPE_UNDEFINED);
     celix_array_list_entry_t entry;
     memset(&entry, 0, sizeof(entry));
     entry.longVal = val;
     return celix_arrayList_addEntry(list, entry);
 }
 
-celix_status_t celix_arrayList_addUInt(celix_array_list_t *list, unsigned int 
val) {
+celix_status_t celix_arrayList_addUInt(celix_array_list_t* list, unsigned int 
val) {
+    assert(list->elementType == CELIX_ARRAY_LIST_ELEMENT_TYPE_UINT ||
+           list->elementType == CELIX_ARRAY_LIST_ELEMENT_TYPE_UNDEFINED);
     celix_array_list_entry_t entry;
     memset(&entry, 0, sizeof(entry));
     entry.uintVal = val;
     return celix_arrayList_addEntry(list, entry);
 }
 
-celix_status_t celix_arrayList_addULong(celix_array_list_t *list, unsigned 
long val) {
+celix_status_t celix_arrayList_addULong(celix_array_list_t* list, unsigned 
long val) {
+    assert(list->elementType == CELIX_ARRAY_LIST_ELEMENT_TYPE_ULONG ||
+           list->elementType == CELIX_ARRAY_LIST_ELEMENT_TYPE_UNDEFINED);
     celix_array_list_entry_t entry;
     memset(&entry, 0, sizeof(entry));
     entry.ulongVal = val;
     return celix_arrayList_addEntry(list, entry);
 }
 
-celix_status_t celix_arrayList_addDouble(celix_array_list_t *list, double val) 
{
+celix_status_t celix_arrayList_addDouble(celix_array_list_t* list, double val) 
{
+    assert(list->elementType == CELIX_ARRAY_LIST_ELEMENT_TYPE_DOUBLE ||
+           list->elementType == CELIX_ARRAY_LIST_ELEMENT_TYPE_UNDEFINED);
     celix_array_list_entry_t entry;
     memset(&entry, 0, sizeof(entry));
     entry.doubleVal = val;
     return celix_arrayList_addEntry(list, entry);
 }
 
-celix_status_t celix_arrayList_addFloat(celix_array_list_t *list, float val) {
+celix_status_t celix_arrayList_addFloat(celix_array_list_t* list, float val) {
+    assert(list->elementType == CELIX_ARRAY_LIST_ELEMENT_TYPE_FLOAT ||
+           list->elementType == CELIX_ARRAY_LIST_ELEMENT_TYPE_UNDEFINED);
     celix_array_list_entry_t entry;
     memset(&entry, 0, sizeof(entry));
     entry.floatVal = val;
     return celix_arrayList_addEntry(list, entry);
 }
 
-celix_status_t celix_arrayList_addBool(celix_array_list_t *list, bool val) {
+celix_status_t celix_arrayList_addBool(celix_array_list_t* list, bool val) {
+    assert(list->elementType == CELIX_ARRAY_LIST_ELEMENT_TYPE_BOOL ||
+           list->elementType == CELIX_ARRAY_LIST_ELEMENT_TYPE_UNDEFINED);
     celix_array_list_entry_t entry;
     memset(&entry, 0, sizeof(entry));
     entry.boolVal = val;
     return celix_arrayList_addEntry(list, entry);
 }
 
-celix_status_t celix_arrayList_addSize(celix_array_list_t *list, size_t val) {
+celix_status_t celix_arrayList_addSize(celix_array_list_t* list, size_t val) {
+    assert(list->elementType == CELIX_ARRAY_LIST_ELEMENT_TYPE_SIZE ||
+           list->elementType == CELIX_ARRAY_LIST_ELEMENT_TYPE_UNDEFINED);
     celix_array_list_entry_t entry;
     memset(&entry, 0, sizeof(entry));
     entry.sizeVal = val;
     return celix_arrayList_addEntry(list, entry);
 }
 
+celix_status_t celix_arrayList_addVersion(celix_array_list_t* list, const 
celix_version_t* value) {
+    assert(list->elementType == CELIX_ARRAY_LIST_ELEMENT_TYPE_VERSION ||
+           list->elementType == CELIX_ARRAY_LIST_ELEMENT_TYPE_UNDEFINED);
+    celix_array_list_entry_t entry;
+    memset(&entry, 0, sizeof(entry));
+    if (list->elementType == CELIX_ARRAY_LIST_ELEMENT_TYPE_VERSION) {
+        entry.versionVal = celix_version_copy(value);
+        if (entry.versionVal == NULL) {
+            return CELIX_ENOMEM;
+        }
+    } else {
+        entry.versionVal = value;
+    }
+    return celix_arrayList_addEntry(list, entry);
+}
+
+celix_status_t celix_arrayList_assignVersion(celix_array_list_t* list, 
celix_version_t* value) {
+    assert(list->elementType == CELIX_ARRAY_LIST_ELEMENT_TYPE_VERSION);
+    celix_array_list_entry_t entry;
+    memset(&entry, 0, sizeof(entry));
+    entry.versionVal = value;
+    return celix_arrayList_addEntry(list, entry);
+}
+
 int celix_arrayList_indexOf(celix_array_list_t *list, celix_array_list_entry_t 
entry) {
     size_t size = celix_arrayList_size(list);
     int i;
@@ -253,70 +579,106 @@ void celix_arrayList_removeEntry(celix_array_list_t 
*list, celix_array_list_entr
     celix_arrayList_removeAt(list, index);
 }
 
-
-void celix_arrayList_remove(celix_array_list_t *list, void *ptr) {
+void celix_arrayList_remove(celix_array_list_t* list, void* ptr) {
+    assert(list->elementType == CELIX_ARRAY_LIST_ELEMENT_TYPE_POINTER ||
+           list->elementType == CELIX_ARRAY_LIST_ELEMENT_TYPE_UNDEFINED);
     celix_array_list_entry_t entry;
     memset(&entry, 0, sizeof(entry));
     entry.voidPtrVal = ptr;
     celix_arrayList_removeEntry(list, entry);
 }
 
-void celix_arrayList_removeInt(celix_array_list_t *list, int val) {
+void celix_arrayList_removeString(celix_array_list_t* list, const char* val) {
+    assert(list->elementType == CELIX_ARRAY_LIST_ELEMENT_TYPE_STRING ||
+           list->elementType == CELIX_ARRAY_LIST_ELEMENT_TYPE_STRING_REF ||
+           list->elementType == CELIX_ARRAY_LIST_ELEMENT_TYPE_UNDEFINED);
+    celix_array_list_entry_t entry;
+    memset(&entry, 0, sizeof(entry));
+    entry.stringVal = val;
+    celix_arrayList_removeEntry(list, entry);
+}
+
+void celix_arrayList_removeInt(celix_array_list_t* list, int val) {
+    assert(list->elementType == CELIX_ARRAY_LIST_ELEMENT_TYPE_INT ||
+           list->elementType == CELIX_ARRAY_LIST_ELEMENT_TYPE_UNDEFINED);
     celix_array_list_entry_t entry;
     memset(&entry, 0, sizeof(entry));
     entry.intVal = val;
     celix_arrayList_removeEntry(list, entry);
 }
 
-void celix_arrayList_removeLong(celix_array_list_t *list, long val) {
+void celix_arrayList_removeLong(celix_array_list_t* list, long val) {
+    assert(list->elementType == CELIX_ARRAY_LIST_ELEMENT_TYPE_LONG ||
+           list->elementType == CELIX_ARRAY_LIST_ELEMENT_TYPE_UNDEFINED);
     celix_array_list_entry_t entry;
     memset(&entry, 0, sizeof(entry));
     entry.longVal = val;
     celix_arrayList_removeEntry(list, entry);
 }
 
-void celix_arrayList_removeUInt(celix_array_list_t *list, unsigned int val) {
+void celix_arrayList_removeUInt(celix_array_list_t* list, unsigned int val) {
+    assert(list->elementType == CELIX_ARRAY_LIST_ELEMENT_TYPE_UINT ||
+           list->elementType == CELIX_ARRAY_LIST_ELEMENT_TYPE_UNDEFINED);
     celix_array_list_entry_t entry;
     memset(&entry, 0, sizeof(entry));
     entry.uintVal = val;
     celix_arrayList_removeEntry(list, entry);
 }
 
-void celix_arrayList_removeULong(celix_array_list_t *list, unsigned long val) {
+void celix_arrayList_removeULong(celix_array_list_t* list, unsigned long val) {
+    assert(list->elementType == CELIX_ARRAY_LIST_ELEMENT_TYPE_ULONG ||
+           list->elementType == CELIX_ARRAY_LIST_ELEMENT_TYPE_UNDEFINED);
     celix_array_list_entry_t entry;
     memset(&entry, 0, sizeof(entry));
     entry.ulongVal = val;
     celix_arrayList_removeEntry(list, entry);
 }
 
-void celix_arrayList_removeFloat(celix_array_list_t *list, float val) {
+void celix_arrayList_removeFloat(celix_array_list_t* list, float val) {
+    assert(list->elementType == CELIX_ARRAY_LIST_ELEMENT_TYPE_FLOAT ||
+           list->elementType == CELIX_ARRAY_LIST_ELEMENT_TYPE_UNDEFINED);
     celix_array_list_entry_t entry;
     memset(&entry, 0, sizeof(entry));
     entry.floatVal = val;
     celix_arrayList_removeEntry(list, entry);
 }
 
-void celix_arrayList_removeDouble(celix_array_list_t *list, double val) {
+void celix_arrayList_removeDouble(celix_array_list_t* list, double val) {
+    assert(list->elementType == CELIX_ARRAY_LIST_ELEMENT_TYPE_DOUBLE ||
+           list->elementType == CELIX_ARRAY_LIST_ELEMENT_TYPE_UNDEFINED);
     celix_array_list_entry_t entry;
     memset(&entry, 0, sizeof(entry));
     entry.doubleVal = val;
     celix_arrayList_removeEntry(list, entry);
 }
 
-void celix_arrayList_removeBool(celix_array_list_t *list, bool val) {
+void celix_arrayList_removeBool(celix_array_list_t* list, bool val) {
+    assert(list->elementType == CELIX_ARRAY_LIST_ELEMENT_TYPE_BOOL ||
+           list->elementType == CELIX_ARRAY_LIST_ELEMENT_TYPE_UNDEFINED);
     celix_array_list_entry_t entry;
     memset(&entry, 0, sizeof(entry));
     entry.boolVal = val;
     celix_arrayList_removeEntry(list, entry);
 }
 
-void celix_arrayList_removeSize(celix_array_list_t *list, size_t val) {
+void celix_arrayList_removeSize(celix_array_list_t* list, size_t val) {
+    assert(list->elementType == CELIX_ARRAY_LIST_ELEMENT_TYPE_SIZE ||
+           list->elementType == CELIX_ARRAY_LIST_ELEMENT_TYPE_UNDEFINED);
     celix_array_list_entry_t entry;
     memset(&entry, 0, sizeof(entry));
     entry.sizeVal = val;
     celix_arrayList_removeEntry(list, entry);
 }
 
+void celix_arrayList_removeVersion(celix_array_list_t* list, const 
celix_version_t* val) {
+    assert(list->elementType == CELIX_ARRAY_LIST_ELEMENT_TYPE_VERSION ||
+           list->elementType == CELIX_ARRAY_LIST_ELEMENT_TYPE_UNDEFINED);
+    celix_array_list_entry_t entry;
+    memset(&entry, 0, sizeof(entry));
+    entry.versionVal = val;
+    celix_arrayList_removeEntry(list, entry);
+}
+
 void celix_arrayList_clear(celix_array_list_t *list) {
     list->modCount++;
     for (int i = 0; i < list->size; ++i) {
@@ -344,24 +706,3 @@ void celix_arrayList_sortEntries(celix_array_list_t *list, 
celix_array_list_comp
     qsort_r(list->elementData, list->size, sizeof(celix_array_list_entry_t), 
celix_arrayList_compareEntries, compare);
 #endif
 }
-
-#if defined(__APPLE__)
-static int celix_arrayList_compare(void *arg, const void * a, const void *b) {
-#else
-static int celix_arrayList_compare(const void * a, const void *b, void *arg) {
-#endif
-    const celix_array_list_entry_t *aEntry = a;
-    const celix_array_list_entry_t *bEntry = b;
-
-    celix_arrayList_sort_fp sort = arg;
-
-    return sort(aEntry->voidPtrVal, bEntry->voidPtrVal);
-}
-
-void celix_arrayList_sort(celix_array_list_t *list, celix_arrayList_sort_fp 
sortFp) {
-#if defined(__APPLE__)
-    qsort_r(list->elementData, list->size, sizeof(celix_array_list_entry_t), 
sortFp, celix_arrayList_compare);
-#else
-    qsort_r(list->elementData, list->size, sizeof(celix_array_list_entry_t), 
celix_arrayList_compare, sortFp);
-#endif
-}
diff --git a/libs/utils/src/array_list_private.h 
b/libs/utils/src/array_list_private.h
deleted file mode 100644
index 1746202d..00000000
--- a/libs/utils/src/array_list_private.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-/**
- * array_list_private.h
- *
- *  \date       Aug 4, 2010
- *  \author     <a href="mailto:[email protected]";>Apache Celix Project 
Team</a>
- *  \copyright  Apache License, Version 2.0
- */
-
-#ifndef array_list_t_PRIVATE_H_
-#define array_list_t_PRIVATE_H_
-
-struct celix_array_list {
-    celix_array_list_entry_t* elementData;
-    size_t size;
-    size_t capacity;
-    unsigned int modCount;
-    celix_arrayList_equals_fp  equals;
-    void (*simpleRemovedCallback)(void* value);
-    void* removedCallbackData;
-    void (*removedCallback)(void* data, celix_array_list_entry_t entry);
-};
-
-#endif /* array_list_t_PRIVATE_H_ */

Reply via email to