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_ */
