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 f0ff9d94eb83ba3589e644988c338086db251b18
Author: Pepijn Noltes <[email protected]>
AuthorDate: Sun Feb 4 23:32:00 2024 +0100

    #674 Add array list element type testing
---
 .../log_admin/gtest/src/LogAdminTestSuite.cc       |   8 -
 bundles/logging/log_admin/src/celix_log_admin.c    |   4 +-
 .../log_service_api/include/celix_log_control.h    |  12 +
 libs/utils/gtest/CMakeLists.txt                    |   2 +-
 libs/utils/gtest/src/ArrayListTestSuite.cc         | 351 ++++++++++++++++-----
 libs/utils/include/celix_array_list.h              |  10 +-
 libs/utils/src/array_list.c                        |  40 ++-
 7 files changed, 330 insertions(+), 97 deletions(-)

diff --git a/bundles/logging/log_admin/gtest/src/LogAdminTestSuite.cc 
b/bundles/logging/log_admin/gtest/src/LogAdminTestSuite.cc
index 859a24a7..fe11a78f 100644
--- a/bundles/logging/log_admin/gtest/src/LogAdminTestSuite.cc
+++ b/bundles/logging/log_admin/gtest/src/LogAdminTestSuite.cc
@@ -208,10 +208,6 @@ TEST_F(LogBundleTestSuite, SinkLogControl) {
 
     auto *list = control->currentSinks(control->handle);
     EXPECT_EQ(3, celix_arrayList_size(list));
-    for (int i = 0; i < celix_arrayList_size(list); ++i) {
-        auto *item = celix_arrayList_get(list, i);
-        free(item);
-    }
     celix_arrayList_destroy(list);
 
 
@@ -277,10 +273,6 @@ TEST_F(LogBundleTestSuite, LogServiceControl) {
 
     auto *list = control->currentLogServices(control->handle);
     EXPECT_EQ(4, celix_arrayList_size(list));
-    for (int i = 0; i < celix_arrayList_size(list); ++i) {
-        auto *item = celix_arrayList_get(list, i);
-        free(item);
-    }
     celix_arrayList_destroy(list);
 
     celix_bundleContext_stopTracker(ctx.get(), trkId1);
diff --git a/bundles/logging/log_admin/src/celix_log_admin.c 
b/bundles/logging/log_admin/src/celix_log_admin.c
index 6b1be0f5..5ed38d53 100644
--- a/bundles/logging/log_admin/src/celix_log_admin.c
+++ b/bundles/logging/log_admin/src/celix_log_admin.c
@@ -544,7 +544,7 @@ static void celix_logAdmin_InfoCmd(celix_log_admin_t* 
admin, FILE* outStream, FI
 
     fprintf(outStream, "Log Admin provided log services:\n");
     for (int i = 0 ; i < celix_arrayList_size(logServices); ++i) {
-        char *name = celix_arrayList_get(logServices, i);
+        const char *name = celix_arrayList_getString(logServices, i);
         celix_log_level_e level;
         bool detailed;
         bool found = celix_logAdmin_logServiceInfoEx(admin, name, &level, 
&detailed);
@@ -558,7 +558,7 @@ static void celix_logAdmin_InfoCmd(celix_log_admin_t* 
admin, FILE* outStream, FI
     if (celix_arrayList_size(sinks) > 0) {
         fprintf(outStream, "Log Admin found log sinks:\n");
         for (int i = 0 ; i < celix_arrayList_size(sinks); ++i) {
-            char *name = celix_arrayList_get(sinks, i);
+            const char *name = celix_arrayList_getString(sinks, i);
             bool enabled;
             bool found = celix_logAdmin_sinkInfo(admin, name, &enabled);
             if (found) {
diff --git a/bundles/logging/log_service_api/include/celix_log_control.h 
b/bundles/logging/log_service_api/include/celix_log_control.h
index 5f3d82f3..98c9a31d 100644
--- a/bundles/logging/log_service_api/include/celix_log_control.h
+++ b/bundles/logging/log_service_api/include/celix_log_control.h
@@ -44,8 +44,20 @@ typedef struct celix_log_control {
 
     size_t (*setSinkEnabled)(void *handle, const char* select, bool enabled);
 
+    /**
+     * @brief Get a list of names for the log service provided by the log 
service.
+     * @param handle The service handle.
+     * @return A string array list.
+     *         The array list is owned by the caller and should be destroyed 
by calling celix_arrayList_destroy.
+     */
     celix_array_list_t* (*currentLogServices)(void *handle);
 
+    /**
+     * @brief Get a list of sinks names used by the log service.
+     * @param handle The service handle.
+     * @return A string array list.
+     *        The array list is owned by the caller and should be destroyed by 
calling celix_arrayList_destroy.
+     */
     celix_array_list_t* (*currentSinks)(void *handle);
 
     bool (*logServiceInfo)(void *handle, const char* loggerName, 
celix_log_level_e* outActiveLogLevel);
diff --git a/libs/utils/gtest/CMakeLists.txt b/libs/utils/gtest/CMakeLists.txt
index e1e22ef7..db39b903 100644
--- a/libs/utils/gtest/CMakeLists.txt
+++ b/libs/utils/gtest/CMakeLists.txt
@@ -34,6 +34,7 @@ add_executable(test_utils
         src/ThreadsTestSuite.cc
         src/CelixErrnoTestSuite.cc
         src/CelixUtilsAutoCleanupTestSuite.cc
+        src/ArrayListTestSuite.cc
         src/DeprecatedHashmapTestSuite.cc
 )
 
@@ -45,7 +46,6 @@ configure_file(resources/properties.txt 
${CMAKE_CURRENT_BINARY_DIR}/resources-te
 
 if (CELIX_CXX17)
     add_library(test_utils_cxx17tests OBJECT
-            src/ArrayListTestSuite.cc #Uses constexpr
             src/HashMapTestSuite.cc   #Uses constexpr
     )
     target_link_libraries(test_utils_cxx17tests PRIVATE utils_cut Celix::utils 
GTest::gtest)
diff --git a/libs/utils/gtest/src/ArrayListTestSuite.cc 
b/libs/utils/gtest/src/ArrayListTestSuite.cc
index 488f069f..6a508188 100644
--- a/libs/utils/gtest/src/ArrayListTestSuite.cc
+++ b/libs/utils/gtest/src/ArrayListTestSuite.cc
@@ -83,76 +83,26 @@ TEST_F(ArrayListTestSuite, TestArrayListWithEquals) {
 }
 
 template<typename T>
-void testArrayListForTemplateType(int nrEntries) {
-    auto* list = celix_arrayList_create();
+void testArrayListForTemplateType(const std::vector<T>& entries,
+                                  const std::function<celix_array_list_t*()>& 
create,
+                                  const 
std::function<celix_status_t(celix_array_list_t*, T)>& add,
+                                  const std::function<T(celix_array_list_t*, 
int)>& get,
+                                  const 
std::function<void(celix_array_list_t*, T)>& remove) {
+    auto* list = create();
     //fill
-    for (int i = 0; i < nrEntries; ++i) {
-        if constexpr (std::is_same_v<void*, T>) {
-            celix_arrayList_add(list, (void*)(intptr_t )i);
-        } else if constexpr (std::is_same_v<int, T>) {
-            celix_arrayList_addInt(list, i);
-        } else if constexpr (std::is_same_v<long, T>) {
-            celix_arrayList_addLong(list, i);
-        } else if constexpr (std::is_same_v<unsigned int, T>) {
-            celix_arrayList_addUInt(list, i);
-        } else if constexpr (std::is_same_v<unsigned long, T>) {
-            celix_arrayList_addULong(list, i);
-        } else if constexpr (std::is_same_v<float, T>) {
-            celix_arrayList_addFloat(list, i + 0.0f);
-        } else if constexpr (std::is_same_v<double, T>) {
-            celix_arrayList_addDouble(list, i + 0.0);
-        } else if constexpr (std::is_same_v<bool, T>) {
-            celix_arrayList_addBool(list, i % 2 == 0);
-        } else if constexpr (std::is_same_v<size_t, T>) {
-            celix_arrayList_addSize(list, i);
-        }
+    for (const auto& entry : entries) {
+        add(list, entry);
     }
-    EXPECT_EQ(celix_arrayList_size(list), nrEntries);
+    EXPECT_EQ(celix_arrayList_size(list), entries.size());
 
     //get
-    for (int i = 0; i < nrEntries; ++i) {
-        if constexpr (std::is_same_v<void*, T>) {
-            EXPECT_EQ(celix_arrayList_get(list, i), (void*)(intptr_t )i);
-        } else if constexpr (std::is_same_v<int, T>) {
-            EXPECT_EQ(celix_arrayList_getInt(list, i), i);
-        } else if constexpr (std::is_same_v<long, T>) {
-            EXPECT_EQ(celix_arrayList_getLong(list, i), i);
-        } else if constexpr (std::is_same_v<unsigned int, T>) {
-            EXPECT_EQ(celix_arrayList_getUInt(list, i), i);
-        } else if constexpr (std::is_same_v<unsigned long, T>) {
-            EXPECT_EQ(celix_arrayList_getULong(list, i), i);
-        } else if constexpr (std::is_same_v<float, T>) {
-            EXPECT_EQ(celix_arrayList_getFloat(list, i), i + 0.0);
-        } else if constexpr (std::is_same_v<double, T>) {
-            EXPECT_EQ(celix_arrayList_getDouble(list, i), i + 0.0);
-        } else if constexpr (std::is_same_v<bool, T>) {
-            EXPECT_EQ(celix_arrayList_getBool(list, i), i % 2 == 0);
-        } else if constexpr (std::is_same_v<size_t, T>) {
-            EXPECT_EQ(celix_arrayList_getSize(list, i), i);
-        }
+    for (int i = 0; i < (int)entries.size(); ++i) {
+        EXPECT_EQ(get(list, i), entries[i]);
     }
 
     //remove
-    for (int i = 0; i < nrEntries; ++i) {
-        if constexpr (std::is_same_v<void*, T>) {
-            celix_arrayList_remove(list, (void*)(intptr_t)i);
-        } else if constexpr (std::is_same_v<int, T>) {
-            celix_arrayList_removeInt(list, i);
-        } else if constexpr (std::is_same_v<long, T>) {
-            celix_arrayList_removeLong(list, i);
-        } else if constexpr (std::is_same_v<unsigned int, T>) {
-            celix_arrayList_removeUInt(list, i);
-        } else if constexpr (std::is_same_v<unsigned long, T>) {
-            celix_arrayList_removeULong(list, i);
-        } else if constexpr (std::is_same_v<float, T>) {
-            celix_arrayList_removeFloat(list, i + 0.0);
-        } else if constexpr (std::is_same_v<double, T>) {
-            celix_arrayList_removeDouble(list, i + 0.0);
-        } else if constexpr (std::is_same_v<bool, T>) {
-            celix_arrayList_removeBool(list, i % 2 == 0);
-        } else if constexpr (std::is_same_v<size_t, T>) {
-            celix_arrayList_removeSize(list, i);
-        }
+    for (int i = 0; i < (int)entries.size(); ++i) {
+        remove(list, entries[i]);
     }
     EXPECT_EQ(celix_arrayList_size(list), 0);
 
@@ -160,15 +110,270 @@ void testArrayListForTemplateType(int nrEntries) {
 }
 
 TEST_F(ArrayListTestSuite, TestDifferentEntyTypesForArrayList) {
-    testArrayListForTemplateType<void*>(10);
-    testArrayListForTemplateType<int>(10);
-    testArrayListForTemplateType<long>(10);
-    testArrayListForTemplateType<unsigned int>(10);
-    testArrayListForTemplateType<unsigned long>(10);
-    testArrayListForTemplateType<float>(10);
-    testArrayListForTemplateType<double>(10);
-    testArrayListForTemplateType<bool>(10);
-    testArrayListForTemplateType<size_t>(10);
+    std::vector<int> intEntries{1, 2, 3, 4, 5};
+    testArrayListForTemplateType<int>(intEntries,
+                                      celix_arrayList_createIntArray,
+                                      celix_arrayList_addInt,
+                                      celix_arrayList_getInt,
+                                      celix_arrayList_removeInt);
+
+    std::vector<long> longEntries{1L, 2L, 3L, 4L, 5L};
+    testArrayListForTemplateType<long>(longEntries,
+                                       celix_arrayList_createLongArray,
+                                       celix_arrayList_addLong,
+                                       celix_arrayList_getLong,
+                                       celix_arrayList_removeLong);
+
+    std::vector<float> floatEntries{1.0f, 2.0f, 3.0f, 4.0f, 5.0f};
+    testArrayListForTemplateType<float>(floatEntries,
+                                        celix_arrayList_createFloatArray,
+                                        celix_arrayList_addFloat,
+                                        celix_arrayList_getFloat,
+                                        celix_arrayList_removeFloat);
+
+    std::vector<double> doubleEntries{1.0, 2.0, 3.0, 4.0, 5.0};
+    testArrayListForTemplateType<double>(doubleEntries,
+                                         celix_arrayList_createDoubleArray,
+                                         celix_arrayList_addDouble,
+                                         celix_arrayList_getDouble,
+                                         celix_arrayList_removeDouble);
+
+    std::vector<bool> boolEntries{true, false, true, false, true};
+    testArrayListForTemplateType<bool>(boolEntries,
+                                       celix_arrayList_createBoolArray,
+                                       celix_arrayList_addBool,
+                                       celix_arrayList_getBool,
+                                       celix_arrayList_removeBool);
+
+    std::vector<void*> voidPtrEntries{(void*)0x11, (void*)0x22, (void*)0x33, 
(void*)0x44, (void*)0x55};
+    testArrayListForTemplateType<void*>(voidPtrEntries,
+                                        celix_arrayList_createPointerArray,
+                                        celix_arrayList_add,
+                                        celix_arrayList_get,
+                                        celix_arrayList_remove);
+
+    std::vector<uint32_t> uintEntries{1, 2, 3, 4, 5};
+    testArrayListForTemplateType<uint32_t>(uintEntries,
+                                           celix_arrayList_createUIntArray,
+                                           celix_arrayList_addUInt,
+                                           celix_arrayList_getUInt,
+                                           celix_arrayList_removeUInt);
+
+    std::vector<uint64_t> ulongEntries{1, 2, 3, 4, 5};
+    testArrayListForTemplateType<uint64_t>(ulongEntries,
+                                           celix_arrayList_createULongArray,
+                                           celix_arrayList_addULong,
+                                           celix_arrayList_getULong,
+                                           celix_arrayList_removeULong);
+
+    std::vector<size_t> sizeEntries{1, 2, 3, 4, 5};
+    testArrayListForTemplateType<size_t>(sizeEntries,
+                                         celix_arrayList_createSizeArray,
+                                         celix_arrayList_addSize,
+                                         celix_arrayList_getSize,
+                                         celix_arrayList_removeSize);
+}
+
+TEST_F(ArrayListTestSuite, StringArrayList) {
+    celix_autoptr(celix_array_list_t) stringList = 
celix_arrayList_createStringArray();
+    const char* str1 = "1";
+    celix_arrayList_addString(stringList, str1);
+    celix_arrayList_addString(stringList, "2");
+    celix_arrayList_assignString(stringList, strdup("3"));
+
+    EXPECT_EQ(3, celix_arrayList_size(stringList));
+    EXPECT_STREQ("1", celix_arrayList_getString(stringList, 0));
+    EXPECT_NE((void*)str1, (void*)celix_arrayList_getString(stringList, 0)); 
//string is added as copy
+    EXPECT_STREQ("2", celix_arrayList_getString(stringList, 1));
+    EXPECT_STREQ("3", celix_arrayList_getString(stringList, 2));
+
+    celix_arrayList_removeString(stringList, "2");
+    EXPECT_EQ(2, celix_arrayList_size(stringList));
+
+    celix_autoptr(celix_array_list_t) stringRefList = 
celix_arrayList_createStringRefArray();
+    celix_arrayList_addString(stringRefList, str1);
+    celix_arrayList_addString(stringRefList, "2");
+    celix_arrayList_addString(stringRefList, "3");
+
+    EXPECT_EQ(3, celix_arrayList_size(stringRefList));
+    EXPECT_STREQ("1", celix_arrayList_getString(stringRefList, 0));
+    EXPECT_EQ((void*)str1, (void*)celix_arrayList_getString(stringRefList, 
0)); //string is added as reference
+    EXPECT_STREQ("2", celix_arrayList_getString(stringRefList, 1));
+
+    celix_arrayList_removeString(stringRefList, "2");
+    EXPECT_EQ(2, celix_arrayList_size(stringRefList));
+}
+
+TEST_F(ArrayListTestSuite, VersionArrayList) {
+    celix_autoptr(celix_array_list_t) versionList = 
celix_arrayList_createVersionArray();
+    celix_version_t* v1 = celix_version_create(1, 2, 3, "a");
+    celix_arrayList_addVersion(versionList, v1); //copy
+    celix_arrayList_assignVersion(versionList, v1); //transfer ownership
+    celix_arrayList_assignVersion(versionList, celix_version_create(2, 3, 4, 
"b"));
+
+    EXPECT_EQ(3, celix_arrayList_size(versionList));
+    EXPECT_EQ(0, 
celix_version_compareToMajorMinor(celix_arrayList_getVersion(versionList, 0), 
1, 2));
+    EXPECT_EQ(0, 
celix_version_compareToMajorMinor(celix_arrayList_getVersion(versionList, 1), 
1, 2));
+    EXPECT_EQ(0, 
celix_version_compareToMajorMinor(celix_arrayList_getVersion(versionList, 2), 
2, 3));
+
+    EXPECT_NE((void*)v1, (void*)celix_arrayList_getVersion(versionList, 0)); 
//version is added as copy
+    EXPECT_EQ((void*)v1, (void*)celix_arrayList_getVersion(versionList, 1)); 
//version is added as reference
+
+    celix_autoptr(celix_version_t) vRef = celix_version_create(1, 2, 3, "a");
+    celix_arrayList_removeVersion(versionList, vRef);
+    EXPECT_EQ(2, celix_arrayList_size(versionList));
+}
+
+TEST_F(ArrayListTestSuite, SortTypedArrayLists) {
+    // Given a ptr, string, int, long, uint, ulong, float, double, bool, size 
and version list
+    // with unsorted values (including duplicates)
+    celix_autoptr(celix_array_list_t) ptrList = 
celix_arrayList_createPointerArray();
+    celix_arrayList_add(ptrList, (void*)0x33);
+    celix_arrayList_add(ptrList, (void*)0x11);
+    celix_arrayList_add(ptrList, (void*)0x22);
+    celix_arrayList_add(ptrList, (void*)0x11);
+
+    celix_autoptr(celix_array_list_t) stringList = 
celix_arrayList_createStringArray();
+    celix_arrayList_addString(stringList, "3");
+    celix_arrayList_addString(stringList, "1");
+    celix_arrayList_addString(stringList, "2");
+    celix_arrayList_addString(stringList, "1");
+
+    celix_autoptr(celix_array_list_t) intList = 
celix_arrayList_createIntArray();
+    celix_arrayList_addInt(intList, 3);
+    celix_arrayList_addInt(intList, 1);
+    celix_arrayList_addInt(intList, 2);
+    celix_arrayList_addInt(intList, 1);
+
+    celix_autoptr(celix_array_list_t) longList = 
celix_arrayList_createLongArray();
+    celix_arrayList_addLong(longList, 3L);
+    celix_arrayList_addLong(longList, 1L);
+    celix_arrayList_addLong(longList, 2L);
+    celix_arrayList_addLong(longList, 1L);
+
+    celix_autoptr(celix_array_list_t) uintList = 
celix_arrayList_createUIntArray();
+    celix_arrayList_addUInt(uintList, 3U);
+    celix_arrayList_addUInt(uintList, 1U);
+    celix_arrayList_addUInt(uintList, 2U);
+    celix_arrayList_addUInt(uintList, 1U);
+
+    celix_autoptr(celix_array_list_t) ulongList = 
celix_arrayList_createULongArray();
+    celix_arrayList_addULong(ulongList, 3UL);
+    celix_arrayList_addULong(ulongList, 1UL);
+    celix_arrayList_addULong(ulongList, 2UL);
+    celix_arrayList_addULong(ulongList, 1UL);
+
+    celix_autoptr(celix_array_list_t) floatList = 
celix_arrayList_createFloatArray();
+    celix_arrayList_addFloat(floatList, 3.0f);
+    celix_arrayList_addFloat(floatList, 1.0f);
+    celix_arrayList_addFloat(floatList, 2.0f);
+    celix_arrayList_addFloat(floatList, 1.0f);
+
+    celix_autoptr(celix_array_list_t) doubleList = 
celix_arrayList_createDoubleArray();
+    celix_arrayList_addDouble(doubleList, 3.0);
+    celix_arrayList_addDouble(doubleList, 1.0);
+    celix_arrayList_addDouble(doubleList, 2.0);
+    celix_arrayList_addDouble(doubleList, 1.0);
+
+    celix_autoptr(celix_array_list_t) boolList = 
celix_arrayList_createBoolArray();
+    celix_arrayList_addBool(boolList, false);
+    celix_arrayList_addBool(boolList, true);
+    celix_arrayList_addBool(boolList, false);
+
+    celix_autoptr(celix_array_list_t) sizeList = 
celix_arrayList_createSizeArray();
+    celix_arrayList_addSize(sizeList, 3);
+    celix_arrayList_addSize(sizeList, 1);
+    celix_arrayList_addSize(sizeList, 2);
+    celix_arrayList_addSize(sizeList, 1);
+
+    celix_autoptr(celix_array_list_t) versionList = 
celix_arrayList_createVersionArray();
+    celix_arrayList_assignVersion(versionList, celix_version_create(2, 1, 0, 
""));
+    celix_arrayList_assignVersion(versionList, celix_version_create(3, 2, 1, 
""));
+    celix_arrayList_assignVersion(versionList, celix_version_create(2, 1, 0, 
""));
+    celix_arrayList_assignVersion(versionList, celix_version_create(1, 0, 0, 
"b"));
+    celix_arrayList_assignVersion(versionList, celix_version_create(1, 0, 0, 
"a"));
+
+    // Then the element type is correctly set
+    EXPECT_EQ(CELIX_ARRAY_LIST_ELEMENT_TYPE_POINTER, 
celix_arrayList_getElementType(ptrList));
+    EXPECT_EQ(CELIX_ARRAY_LIST_ELEMENT_TYPE_STRING, 
celix_arrayList_getElementType(stringList));
+    EXPECT_EQ(CELIX_ARRAY_LIST_ELEMENT_TYPE_INT, 
celix_arrayList_getElementType(intList));
+    EXPECT_EQ(CELIX_ARRAY_LIST_ELEMENT_TYPE_LONG, 
celix_arrayList_getElementType(longList));
+    EXPECT_EQ(CELIX_ARRAY_LIST_ELEMENT_TYPE_UINT, 
celix_arrayList_getElementType(uintList));
+    EXPECT_EQ(CELIX_ARRAY_LIST_ELEMENT_TYPE_ULONG, 
celix_arrayList_getElementType(ulongList));
+    EXPECT_EQ(CELIX_ARRAY_LIST_ELEMENT_TYPE_FLOAT, 
celix_arrayList_getElementType(floatList));
+    EXPECT_EQ(CELIX_ARRAY_LIST_ELEMENT_TYPE_DOUBLE, 
celix_arrayList_getElementType(doubleList));
+    EXPECT_EQ(CELIX_ARRAY_LIST_ELEMENT_TYPE_BOOL, 
celix_arrayList_getElementType(boolList));
+    EXPECT_EQ(CELIX_ARRAY_LIST_ELEMENT_TYPE_SIZE, 
celix_arrayList_getElementType(sizeList));
+    EXPECT_EQ(CELIX_ARRAY_LIST_ELEMENT_TYPE_VERSION, 
celix_arrayList_getElementType(versionList));
+
+    // When sorting the lists
+    celix_arrayList_sort(ptrList);
+    celix_arrayList_sort(stringList);
+    celix_arrayList_sort(intList);
+    celix_arrayList_sort(longList);
+    celix_arrayList_sort(uintList);
+    celix_arrayList_sort(ulongList);
+    celix_arrayList_sort(floatList);
+    celix_arrayList_sort(doubleList);
+    celix_arrayList_sort(boolList);
+    celix_arrayList_sort(sizeList);
+    celix_arrayList_sort(versionList);
+
+    // Then the lists are sorted
+    EXPECT_EQ((void*)0x11, celix_arrayList_get(ptrList, 0));
+    EXPECT_EQ((void*)0x11, celix_arrayList_get(ptrList, 1));
+    EXPECT_EQ((void*)0x22, celix_arrayList_get(ptrList, 2));
+    EXPECT_EQ((void*)0x33, celix_arrayList_get(ptrList, 3));
+
+    EXPECT_STREQ("1", celix_arrayList_getString(stringList, 0));
+    EXPECT_STREQ("1", celix_arrayList_getString(stringList, 1));
+    EXPECT_STREQ("2", celix_arrayList_getString(stringList, 2));
+    EXPECT_STREQ("3", celix_arrayList_getString(stringList, 3));
+
+    EXPECT_EQ(1, celix_arrayList_getInt(intList, 0));
+    EXPECT_EQ(1, celix_arrayList_getInt(intList, 1));
+    EXPECT_EQ(2, celix_arrayList_getInt(intList, 2));
+    EXPECT_EQ(3, celix_arrayList_getInt(intList, 3));
+
+    EXPECT_EQ(1L, celix_arrayList_getLong(longList, 0));
+    EXPECT_EQ(1L, celix_arrayList_getLong(longList, 1));
+    EXPECT_EQ(2L, celix_arrayList_getLong(longList, 2));
+    EXPECT_EQ(3L, celix_arrayList_getLong(longList, 3));
+
+    EXPECT_EQ(1U, celix_arrayList_getUInt(uintList, 0));
+    EXPECT_EQ(1U, celix_arrayList_getUInt(uintList, 1));
+    EXPECT_EQ(2U, celix_arrayList_getUInt(uintList, 2));
+    EXPECT_EQ(3U, celix_arrayList_getUInt(uintList, 3));
+
+    EXPECT_EQ(1UL, celix_arrayList_getULong(ulongList, 0));
+    EXPECT_EQ(1UL, celix_arrayList_getULong(ulongList, 1));
+    EXPECT_EQ(2UL, celix_arrayList_getULong(ulongList, 2));
+    EXPECT_EQ(3UL, celix_arrayList_getULong(ulongList, 3));
+
+    EXPECT_FLOAT_EQ(1.0f, celix_arrayList_getFloat(floatList, 0));
+    EXPECT_FLOAT_EQ(1.0f, celix_arrayList_getFloat(floatList, 1));
+    EXPECT_FLOAT_EQ(2.0f, celix_arrayList_getFloat(floatList, 2));
+    EXPECT_FLOAT_EQ(3.0f, celix_arrayList_getFloat(floatList, 3));
+
+    EXPECT_DOUBLE_EQ(1.0, celix_arrayList_getDouble(doubleList, 0));
+    EXPECT_DOUBLE_EQ(1.0, celix_arrayList_getDouble(doubleList, 1));
+    EXPECT_DOUBLE_EQ(2.0, celix_arrayList_getDouble(doubleList, 2));
+    EXPECT_DOUBLE_EQ(3.0, celix_arrayList_getDouble(doubleList, 3));
+
+    EXPECT_FALSE(celix_arrayList_getBool(boolList, 0));
+    EXPECT_FALSE(celix_arrayList_getBool(boolList, 1));
+    EXPECT_TRUE(celix_arrayList_getBool(boolList, 2));
+
+    EXPECT_EQ(1, celix_arrayList_getSize(sizeList, 0));
+    EXPECT_EQ(1, celix_arrayList_getSize(sizeList, 1));
+    EXPECT_EQ(2, celix_arrayList_getSize(sizeList, 2));
+    EXPECT_EQ(3, celix_arrayList_getSize(sizeList, 3));
+
+    EXPECT_EQ(0, 
celix_version_compareToMajorMinor(celix_arrayList_getVersion(versionList, 0), 
1, 0));
+    EXPECT_EQ(0, 
celix_version_compareToMajorMinor(celix_arrayList_getVersion(versionList, 1), 
1, 0));
+    EXPECT_EQ(0, 
celix_version_compareToMajorMinor(celix_arrayList_getVersion(versionList, 2), 
2, 1));
+    EXPECT_EQ(0, 
celix_version_compareToMajorMinor(celix_arrayList_getVersion(versionList, 3), 
2, 1));
+    EXPECT_EQ(0, 
celix_version_compareToMajorMinor(celix_arrayList_getVersion(versionList, 4), 
3, 2));
 }
 
 TEST_F(ArrayListTestSuite, TestSimpleRemovedCallbacksForArrayList) {
@@ -261,4 +466,4 @@ TEST_F(ArrayListTestSuite, TestReturnStatusAddFunctions) {
 TEST_F(ArrayListTestSuite, AutoCleanupTest) {
     celix_autoptr(celix_array_list_t) list = celix_arrayList_create();
     EXPECT_NE(nullptr, list);
-}
\ 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 25925c89..b4c2dc58 100644
--- a/libs/utils/include/celix_array_list.h
+++ b/libs/utils/include/celix_array_list.h
@@ -294,7 +294,9 @@ 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.
+ * If the element type is set to something other than 
CELIX_ARRAY_LIST_ELEMENT_TYPE_UNDEFINED, the remove, equals,
+ * and compare callbacks will be set according to the corresponding 
celix_arrayList_create*Array function.
+ * The provided callbacks in the options will override the default callbacks.
  *
  * @param opts The create options, only used during the creation of the array 
list.
  */
@@ -311,6 +313,12 @@ void celix_arrayList_destroy(celix_array_list_t *list);
 
 CELIX_DEFINE_AUTOPTR_CLEANUP_FUNC(celix_array_list_t, celix_arrayList_destroy)
 
+/**
+ * @brief Return the element type of the array list.
+ */
+CELIX_UTILS_EXPORT
+celix_array_list_element_type_t celix_arrayList_getElementType(const 
celix_array_list_t *list);
+
 /**
  * @brief Returns the size of the array list.
  */
diff --git a/libs/utils/src/array_list.c b/libs/utils/src/array_list.c
index 807d21b2..cf668150 100644
--- a/libs/utils/src/array_list.c
+++ b/libs/utils/src/array_list.c
@@ -16,13 +16,6 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-/**
- * array_list.c
- *
- *  \date       Aug 4, 2010
- *  \author     <a href="mailto:[email protected]";>Apache Celix Project 
Team</a>
- *  \copyright  Apache License, Version 2.0
- */
 
 #include <assert.h>
 #include <stdint.h>
@@ -50,7 +43,7 @@ struct celix_array_list {
 };
 
 static bool celix_arrayList_undefinedEquals(celix_array_list_entry_t a, 
celix_array_list_entry_t b) {
-    return memcmp(&a, &b, sizeof(a)) == 0;
+    return memcmp(&a.voidPtrVal, &b.voidPtrVal, sizeof(a)) == 0;
 }
 
 static int celix_arrayList_comparePtrEntries(celix_array_list_entry_t a, 
celix_array_list_entry_t b) {
@@ -195,6 +188,10 @@ static void 
celix_arrayList_setTypeSpecificCallbacks(celix_array_list_t* list) {
         list->equalsCallback = celix_arrayList_stringEquals;
         list->compareCallback = celix_arrayList_compareStringEntries;
         break;
+    case CELIX_ARRAY_LIST_ELEMENT_TYPE_STRING_REF:
+        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;
@@ -252,6 +249,7 @@ celix_array_list_t* celix_arrayList_createWithOptions(const 
celix_array_list_cre
         list->elementType = opts->elementType;
         celix_arrayList_setTypeSpecificCallbacks(list);
 
+        //if opts contains callbacks, use them and override the default ones
         if (opts->simpleRemovedCallback) {
             list->simpleRemovedCallback = opts->simpleRemovedCallback;
         }
@@ -259,6 +257,12 @@ celix_array_list_t* 
celix_arrayList_createWithOptions(const celix_array_list_cre
             list->removedCallback = opts->removedCallback;
             list->removedCallbackData = opts->removedCallbackData;
         }
+        if (opts->equalsCallback) {
+            list->equalsCallback = opts->equalsCallback;
+        }
+        if (opts->compareCallback) {
+            list->compareCallback = opts->compareCallback;
+        }
     }
     return celix_steal_ptr(list);
 }
@@ -317,6 +321,11 @@ celix_array_list_t* celix_arrayList_createSizeArray() {
     return 
celix_arrayList_createTypedArray(CELIX_ARRAY_LIST_ELEMENT_TYPE_SIZE);
 }
 
+celix_array_list_t* celix_arrayList_createVersionArray() {
+    return 
celix_arrayList_createTypedArray(CELIX_ARRAY_LIST_ELEMENT_TYPE_VERSION);
+}
+
+
 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;
@@ -331,6 +340,10 @@ void celix_arrayList_destroy(celix_array_list_t *list) {
     }
 }
 
+celix_array_list_element_type_t celix_arrayList_getElementType(const 
celix_array_list_t *list) {
+    return list->elementType;
+}
+
 int celix_arrayList_size(const celix_array_list_t *list) {
     return (int)list->size;
 }
@@ -448,10 +461,7 @@ celix_status_t 
celix_arrayList_assignString(celix_array_list_t* list, char* valu
     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;
-    }
+    entry.stringVal = value;
     return celix_arrayList_addEntry(list, entry);
 }
 
@@ -699,6 +709,12 @@ static int celix_arrayList_compareEntries(const void* 
voidA, const void* voidB,
     return compare(*a, *b);
 }
 
+void celix_arrayList_sort(celix_array_list_t *list) {
+    if (list->compareCallback) {
+        celix_arrayList_sortEntries(list, list->compareCallback);
+    }
+}
+
 void celix_arrayList_sortEntries(celix_array_list_t *list, 
celix_array_list_compare_entries_fp compare) {
 #if defined(__APPLE__)
     qsort_r(list->elementData, list->size, sizeof(celix_array_list_entry_t), 
compare, celix_arrayList_compareEntries);

Reply via email to