Skip to content

Commit

Permalink
#674 Add array list equal and copy function
Browse files Browse the repository at this point in the history
  • Loading branch information
pnoltes committed Feb 5, 2024
1 parent f0ff9d9 commit 1f324c5
Show file tree
Hide file tree
Showing 3 changed files with 175 additions and 19 deletions.
61 changes: 61 additions & 0 deletions libs/utils/gtest/src/ArrayListTestSuite.cc
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,67 @@ TEST_F(ArrayListTestSuite, SortTypedArrayLists) {
EXPECT_EQ(0, celix_version_compareToMajorMinor(celix_arrayList_getVersion(versionList, 4), 3, 2));
}

TEST_F(ArrayListTestSuite, EqualCheck) {
//Given a selection of long list and a double list
celix_autoptr(celix_array_list_t) list1 = celix_arrayList_createLongArray();
celix_arrayList_addLong(list1, 1L);
celix_autoptr(celix_array_list_t) list2 = celix_arrayList_createLongArray(); //same as list1
celix_arrayList_addLong(list2, 1L);
celix_autoptr(celix_array_list_t) list3 = celix_arrayList_createLongArray(); //different values than list1
celix_arrayList_addLong(list3, 2L);
celix_autoptr(celix_array_list_t) list4 = celix_arrayList_createLongArray(); //different size than list1
celix_arrayList_addLong(list4, 1L);
celix_arrayList_addLong(list4, 2L);
celix_autoptr(celix_array_list_t) list5 = celix_arrayList_createDoubleArray(); //different type than list1
celix_arrayList_addDouble(list5, 1.0);

//The lists can be checked for equality
EXPECT_TRUE(celix_arrayList_equals(list1, list2));
EXPECT_TRUE(celix_arrayList_equals(list1, list1));
EXPECT_TRUE(celix_arrayList_equals(nullptr, nullptr));

EXPECT_FALSE(celix_arrayList_equals(nullptr, list1));
EXPECT_FALSE(celix_arrayList_equals(list1, nullptr));
EXPECT_FALSE(celix_arrayList_equals(list1, list3));
EXPECT_FALSE(celix_arrayList_equals(list1, list4));
EXPECT_FALSE(celix_arrayList_equals(list1, list5));
}

TEST_F(ArrayListTestSuite, CopyArrayTest) {
// Given a long, string, string ref and version list
celix_autoptr(celix_array_list_t) longList = celix_arrayList_createLongArray();
celix_arrayList_addLong(longList, 1L);
celix_arrayList_addLong(longList, 2L);
celix_arrayList_addLong(longList, 3L);

celix_autoptr(celix_array_list_t) stringList = celix_arrayList_createStringArray();
celix_arrayList_addString(stringList, "1");
celix_arrayList_addString(stringList, "2");
celix_arrayList_addString(stringList, "3");

celix_autoptr(celix_array_list_t) stringRefList = celix_arrayList_createStringRefArray();
celix_arrayList_addString(stringRefList, "1");
celix_arrayList_addString(stringRefList, "2");
celix_arrayList_addString(stringRefList, "3");

celix_autoptr(celix_array_list_t) versionList = celix_arrayList_createVersionArray();
celix_arrayList_assignVersion(versionList, celix_version_create(1, 0, 0, ""));
celix_arrayList_assignVersion(versionList, celix_version_create(2, 0, 0, ""));
celix_arrayList_assignVersion(versionList, celix_version_create(3, 0, 0, ""));

// When copying the lists
celix_autoptr(celix_array_list_t) longListCopy = celix_arrayList_copy(longList);
celix_autoptr(celix_array_list_t) stringListCopy = celix_arrayList_copy(stringList);
celix_autoptr(celix_array_list_t) stringRefListCopy = celix_arrayList_copy(stringRefList);
celix_autoptr(celix_array_list_t) versionListCopy = celix_arrayList_copy(versionList);

// Then the copied lists are equal to the original lists
EXPECT_TRUE(celix_arrayList_equals(longList, longListCopy));
EXPECT_TRUE(celix_arrayList_equals(stringList, stringListCopy));
EXPECT_TRUE(celix_arrayList_equals(stringRefList, stringRefListCopy));
EXPECT_TRUE(celix_arrayList_equals(versionList, versionListCopy));
}

TEST_F(ArrayListTestSuite, TestSimpleRemovedCallbacksForArrayList) {
celix_array_list_create_options_t opts{};
opts.simpleRemovedCallback = free;
Expand Down
73 changes: 54 additions & 19 deletions libs/utils/include/celix_array_list.h
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ typedef struct celix_array_list_create_options {

#ifndef __cplusplus
/**
* @brief C Macro to create a empty string_hash_map_create_options_t type.
* @brief C Macro to create a empty celix_array_list_create_options_t type.
*/
#define CELIX_EMPTY_ARRAY_LIST_CREATE_OPTIONS \
{ \
Expand Down Expand Up @@ -331,7 +331,7 @@ int celix_arrayList_size(const celix_array_list_t *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 list The array list.
* @param index The entry index to return.
* @return Returns the pointer value for the index. Returns NULL if index is out of bound.
*/
Expand All @@ -357,7 +357,7 @@ const char* celix_arrayList_getString(const celix_array_list_t *list, int 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 list 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.
*/
Expand All @@ -370,7 +370,7 @@ int celix_arrayList_getInt(const celix_array_list_t *list, int 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 list The array list.
* @param index The entry index to return.
* @return Returns the long value for the index. Returns 0 if index is out of bound.
*/
Expand All @@ -383,7 +383,7 @@ long int celix_arrayList_getLong(const celix_array_list_t *list, int 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 list 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.
*/
Expand All @@ -396,7 +396,7 @@ unsigned int celix_arrayList_getUInt(const celix_array_list_t *list, int 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 list 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.
*/
Expand All @@ -409,7 +409,7 @@ unsigned long int celix_arrayList_getULong(const celix_array_list_t *list, int i
* 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 list 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.
*/
Expand All @@ -422,7 +422,7 @@ float celix_arrayList_getFloat(const celix_array_list_t *list, int 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 list The array list.
* @param index The entry index to return.
* @return Returns the double value for the index. Returns 0 if index is out of bound.
*/
Expand All @@ -435,7 +435,7 @@ double celix_arrayList_getDouble(const celix_array_list_t *list, int 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 list The array list.
* @param index The entry index to return.
* @return Returns the bool value for the index. Returns false if index is out of bound.
*/
Expand All @@ -448,7 +448,7 @@ bool celix_arrayList_getBool(const celix_array_list_t *list, int 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 list 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.
*/
Expand All @@ -474,7 +474,7 @@ const celix_version_t* celix_arrayList_getVersion(const celix_array_list_t *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 list 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.
*/
Expand Down Expand Up @@ -518,7 +518,7 @@ celix_status_t celix_arrayList_assignString(celix_array_list_t* list, char* valu
* 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 list 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.
*/
Expand All @@ -531,7 +531,7 @@ celix_status_t celix_arrayList_addInt(celix_array_list_t* list, int value);
* 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 list 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.
*/
Expand All @@ -544,7 +544,7 @@ celix_status_t celix_arrayList_addLong(celix_array_list_t* list, long value);
* 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 list 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.
*/
Expand All @@ -557,7 +557,7 @@ celix_status_t celix_arrayList_addUInt(celix_array_list_t* list, unsigned int va
* 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 list 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.
*/
Expand All @@ -570,7 +570,7 @@ celix_status_t celix_arrayList_addULong(celix_array_list_t* list, unsigned long
* 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 list 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.
*/
Expand All @@ -583,7 +583,7 @@ celix_status_t celix_arrayList_addFloat(celix_array_list_t* list, float value);
* 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 list 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.
*/
Expand All @@ -596,7 +596,7 @@ celix_status_t celix_arrayList_addDouble(celix_array_list_t* list, double value)
* 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 list 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.
*/
Expand All @@ -609,7 +609,7 @@ celix_status_t celix_arrayList_addBool(celix_array_list_t* list, bool value);
* 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 list 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.
*/
Expand Down Expand Up @@ -835,6 +835,41 @@ void celix_arrayList_sortEntries(celix_array_list_t *list, celix_array_list_comp
CELIX_UTILS_EXPORT
void celix_arrayList_sort(celix_array_list_t *list);

/**
* @brief Check if the array list are equal.
*
* Equal is defined as:
* - The array list have the same size
* - The array list have the same element type
* - The array list have the same equals callback
* - The array list have the same values at the same index
*
* Note that the remove callback and compare callback are ignored.
*
* If both array list are NULL, they are considered equal.
*
* @param listA The first array list.
* @param listB The second array list.
* @return true if the array list are equal, false otherwise.
*/
CELIX_UTILS_EXPORT
bool celix_arrayList_equals(const celix_array_list_t* listA, const celix_array_list_t* listB);

/**
* @Brief Copy the array list to a new array list.
*
* The new array list will have the same element type and the same callbacks as the original array list.
* If the element type is CELIX_ARRAY_LIST_ELEMENT_TYPE_STRING, the strings will be copied and
* if the element type is CELIX_ARRAY_LIST_ELEMENT_TYPE_VERSION, the versions will be copied.
* For all other element types the values will be copied.
*
* @param[in] list The array list to copy.
* @return A new array list with the same element type and values as the original array list or NULL if the original
* array list is NULL or out of memory.
*/
CELIX_UTILS_EXPORT
celix_array_list_t* celix_arrayList_copy(const celix_array_list_t* list);

#ifdef __cplusplus
}
#endif
Expand Down
60 changes: 60 additions & 0 deletions libs/utils/src/array_list.c
Original file line number Diff line number Diff line change
Expand Up @@ -715,6 +715,66 @@ void celix_arrayList_sort(celix_array_list_t *list) {
}
}

bool celix_arrayList_equals(const celix_array_list_t* listA, const celix_array_list_t* listB) {
if (listA == listB) {
return true;
}
if (!listA || !listB) {
return false;
}
if (listA->size != listB->size) {
return false;
}
if (listA->equalsCallback != listB->equalsCallback) {
return false;
}
for (int i = 0; i < listA->size; ++i) {
if (!listA->equalsCallback(listA->elementData[i], listB->elementData[i])) {
return false;
}
}
return true;
}

celix_array_list_t* celix_arrayList_copy(const celix_array_list_t* list) {
celix_array_list_create_options_t opts = CELIX_EMPTY_ARRAY_LIST_CREATE_OPTIONS;
opts.elementType = list->elementType;
opts.equalsCallback = list->equalsCallback;
opts.compareCallback = list->compareCallback;
opts.removedCallback = list->removedCallback;
opts.removedCallbackData = list->removedCallbackData;
opts.simpleRemovedCallback = list->simpleRemovedCallback;
celix_autoptr(celix_array_list_t) copy = celix_arrayList_createWithOptions(&opts);
if (!copy) {
celix_err_push("Failed to create copy list. Out of memory.");
return NULL;
}

for (int i = 0; i < celix_arrayList_size(list); ++i) {
celix_array_list_entry_t entry = list->elementData[i];
if (copy->elementType == CELIX_ARRAY_LIST_ELEMENT_TYPE_STRING) {
entry.stringVal = celix_utils_strdup(entry.stringVal);
if (entry.stringVal == NULL) {
celix_err_push("Failed to copy string entry. Out of memory.");
return NULL;
}
} else if (copy->elementType == CELIX_ARRAY_LIST_ELEMENT_TYPE_VERSION) {
entry.versionVal = celix_version_copy(entry.versionVal);
if (entry.versionVal == NULL) {
celix_err_push("Failed to copy version entry. Out of memory.");
return NULL;
}
}
celix_status_t status = celix_arrayList_addEntry(copy, entry);
if (status != CELIX_SUCCESS) {
celix_err_push("Failed to add entry to copy list.");
return NULL;
}
}

return celix_steal_ptr(copy);
}

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);
Expand Down

0 comments on commit 1f324c5

Please sign in to comment.