This is an automated email from the ASF dual-hosted git repository.
pnoltes pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/celix.git
The following commit(s) were added to refs/heads/master by this push:
new b112b3c7f Feature/fix array list initial capability bug (#810)
b112b3c7f is described below
commit b112b3c7f6b551274bf8bc1d8805d055b54e4044
Author: Pepijn Noltes <[email protected]>
AuthorDate: Sat Jan 3 21:14:55 2026 +0100
Feature/fix array list initial capability bug (#810)
Use initialCapacity option in celix array list
---
.../gtest/src/ArrayListErrorInjectionTestSuite.cc | 17 ++++++
libs/utils/gtest/src/ArrayListTestSuite.cc | 12 +++++
libs/utils/include/celix_array_list.h | 60 ++++++++++++----------
libs/utils/src/array_list.c | 46 ++++++++---------
4 files changed, 85 insertions(+), 50 deletions(-)
diff --git a/libs/utils/gtest/src/ArrayListErrorInjectionTestSuite.cc
b/libs/utils/gtest/src/ArrayListErrorInjectionTestSuite.cc
index 6f95a4a6d..9adb1a6ee 100644
--- a/libs/utils/gtest/src/ArrayListErrorInjectionTestSuite.cc
+++ b/libs/utils/gtest/src/ArrayListErrorInjectionTestSuite.cc
@@ -160,3 +160,20 @@ TEST_F(ArrayListErrorInjectionTestSuite,
CopyArrayListFailureTest) {
// And a celix_err is expected
EXPECT_EQ(3, celix_err_getErrorCount());
}
+
+
+TEST_F(ArrayListErrorInjectionTestSuite, InitialCapacityOptionUsed) {
+ celix_array_list_create_options_t opts{};
+ opts.elementType = CELIX_ARRAY_LIST_ELEMENT_TYPE_STRING;
+ opts.initialCapacity = 1; // smaller than number of elements we will add
+ celix_autoptr(celix_array_list_t) list =
celix_arrayList_createWithOptions(&opts);
+
+ // Fail the next realloc to verify that a second add triggers a
reallocation
+ celix_ei_expect_realloc((void*)celix_arrayList_addString, 2, nullptr, 1);
+
+ // First add fits in initial capacity
+ EXPECT_EQ(CELIX_SUCCESS, celix_arrayList_addString(list, "v1"));
+
+ // Second add triggers reallocation and fails
+ EXPECT_EQ(CELIX_ENOMEM, celix_arrayList_addString(list, "v2"));
+}
diff --git a/libs/utils/gtest/src/ArrayListTestSuite.cc
b/libs/utils/gtest/src/ArrayListTestSuite.cc
index c9219b9fb..b35b0a235 100644
--- a/libs/utils/gtest/src/ArrayListTestSuite.cc
+++ b/libs/utils/gtest/src/ArrayListTestSuite.cc
@@ -507,3 +507,15 @@ TEST_F(ArrayListTestSuite, ElementTypeToStringTest) {
EXPECT_STREQ("Undefined",
celix_arrayList_elementTypeToString((celix_array_list_element_type_t)100 /*non
existing*/));
}
+
+TEST_F(ArrayListTestSuite, InitialCapacityOptionTest) {
+ celix_array_list_create_options_t opts{};
+ opts.elementType = CELIX_ARRAY_LIST_ELEMENT_TYPE_STRING;
+ opts.initialCapacity = 1; // smaller than number of elements we will add
+ celix_autoptr(celix_array_list_t) list =
celix_arrayList_createWithOptions(&opts);
+
+ // First add fits in initial capacity
+ EXPECT_EQ(CELIX_SUCCESS, celix_arrayList_addString(list, "v1"));
+ // Second add requires realloc
+ EXPECT_EQ(CELIX_SUCCESS, celix_arrayList_addString(list, "v2"));
+}
diff --git a/libs/utils/include/celix_array_list.h
b/libs/utils/include/celix_array_list.h
index 8393bc238..bc78b216a 100644
--- a/libs/utils/include/celix_array_list.h
+++ b/libs/utils/include/celix_array_list.h
@@ -20,9 +20,9 @@
#include <stdbool.h>
#include "celix_array_list_type.h"
-#include "celix_utils_export.h"
#include "celix_cleanup.h"
#include "celix_errno.h"
+#include "celix_utils_export.h"
#include "celix_version_type.h"
#ifndef CELIX_ARRAY_LIST_H_
@@ -32,12 +32,13 @@
* Init macro so that the opts are correctly initialized for C++ compilers
*/
#ifdef __cplusplus
-#define CELIX_OPTS_INIT {}
+#define CELIX_OPTS_INIT
\
+ {
\
+ }
#else
#define CELIX_OPTS_INIT
#endif
-
#ifdef __cplusplus
extern "C" {
#endif
@@ -57,7 +58,7 @@ typedef enum celix_array_list_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_LONG = 3, /**< Represents a long integer
element type. */
CELIX_ARRAY_LIST_ELEMENT_TYPE_DOUBLE = 4, /**< Represents a double element
type. */
- CELIX_ARRAY_LIST_ELEMENT_TYPE_BOOL = 5, /**< Represents a boolean element
type. */
+ CELIX_ARRAY_LIST_ELEMENT_TYPE_BOOL = 5, /**< Represents a boolean
element type. */
CELIX_ARRAY_LIST_ELEMENT_TYPE_VERSION = 6, /**< Represents a
celix_version_t* element type. */
} celix_array_list_element_type_t;
@@ -75,10 +76,10 @@ typedef union celix_array_list_entry {
CELIX_ARRAY_LIST_ELEMENT_TYPE_STRING_REF or
CELIX_ARRAY_LIST_ELEMENT_TYPE_UNDEFINED. */
long int longVal; /**< A long integer value when the element type is
CELIX_ARRAY_LIST_ELEMENT_TYPE_LONG or
CELIX_ARRAY_LIST_ELEMENT_TYPE_UNDEFINED. */
- double doubleVal; /**< A double value when the element type is
CELIX_ARRAY_LIST_ELEMENT_TYPE_DOUBLE or
- 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. */
+ double doubleVal; /**< A double value when the element type is
CELIX_ARRAY_LIST_ELEMENT_TYPE_DOUBLE 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. */
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;
@@ -252,9 +253,14 @@ typedef struct celix_array_list_create_options {
*/
#define CELIX_EMPTY_ARRAY_LIST_CREATE_OPTIONS
\
{
\
- .elementType = CELIX_ARRAY_LIST_ELEMENT_TYPE_UNDEFINED,
.simpleRemovedCallback = NULL, \
- .removedCallbackData = NULL, .removedCallback = NULL, .equalsCallback
= NULL, \
- .compareCallback = NULL, .copyCallback = NULL,
\
+ .elementType = CELIX_ARRAY_LIST_ELEMENT_TYPE_UNDEFINED,
\
+ .simpleRemovedCallback = NULL,
\
+ .removedCallbackData = NULL,
\
+ .removedCallback = NULL,
\
+ .equalsCallback = NULL,
\
+ .compareCallback = NULL,
\
+ .copyCallback = NULL,
\
+ .initialCapacity = 0,
\
}
#endif
@@ -280,7 +286,7 @@ celix_array_list_t* celix_arrayList_createWithOptions(const
celix_array_list_cre
* @note If a (simple) removed callback is configured, the callback will be
called for every array list entry.
*/
CELIX_UTILS_EXPORT
-void celix_arrayList_destroy(celix_array_list_t *list);
+void celix_arrayList_destroy(celix_array_list_t* list);
CELIX_DEFINE_AUTOPTR_CLEANUP_FUNC(celix_array_list_t, celix_arrayList_destroy)
@@ -288,13 +294,13 @@ 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);
+celix_array_list_element_type_t celix_arrayList_getElementType(const
celix_array_list_t* list);
/**
* @brief Returns the size of the array list.
*/
CELIX_UTILS_EXPORT
-int celix_arrayList_size(const celix_array_list_t *list);
+int celix_arrayList_size(const celix_array_list_t* list);
/**
* @brief Returns the value for the provided index.
@@ -307,7 +313,7 @@ int celix_arrayList_size(const celix_array_list_t *list);
* @return Returns the pointer value for the index. Returns NULL if index is
out of bound.
*/
CELIX_UTILS_EXPORT
-void* celix_arrayList_get(const celix_array_list_t *list, int index);
+void* celix_arrayList_get(const celix_array_list_t* list, int index);
/**
* @brief Returns the value for the provided index.
@@ -320,7 +326,7 @@ void* celix_arrayList_get(const celix_array_list_t *list,
int index);
* @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);
+const char* celix_arrayList_getString(const celix_array_list_t* list, int
index);
/**
* @brief Returns the value for the provided index.
@@ -333,7 +339,7 @@ const char* celix_arrayList_getString(const
celix_array_list_t *list, int index)
* @return Returns the long value for the index. Returns 0 if index is out of
bound.
*/
CELIX_UTILS_EXPORT
-long int celix_arrayList_getLong(const celix_array_list_t *list, int index);
+long int celix_arrayList_getLong(const celix_array_list_t* list, int index);
/**
* @brief Returns the value for the provided index.
@@ -346,7 +352,7 @@ long int celix_arrayList_getLong(const celix_array_list_t
*list, int index);
* @return Returns the double value for the index. Returns 0 if index is out
of bound.
*/
CELIX_UTILS_EXPORT
-double celix_arrayList_getDouble(const celix_array_list_t *list, int index);
+double celix_arrayList_getDouble(const celix_array_list_t* list, int index);
/**
* @brief Returns the value for the provided index.
@@ -359,7 +365,7 @@ double celix_arrayList_getDouble(const celix_array_list_t
*list, int index);
* @return Returns the bool value for the index. Returns false if index is out
of bound.
*/
CELIX_UTILS_EXPORT
-bool celix_arrayList_getBool(const celix_array_list_t *list, int index);
+bool celix_arrayList_getBool(const celix_array_list_t* list, int index);
/**
* @brief Returns the value for the provided index.
@@ -372,7 +378,7 @@ bool celix_arrayList_getBool(const celix_array_list_t
*list, int index);
* @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);
+const celix_version_t* celix_arrayList_getVersion(const celix_array_list_t*
list, int index);
/**
* @brief Returns the entry for the provided index.
@@ -382,7 +388,7 @@ const celix_version_t* celix_arrayList_getVersion(const
celix_array_list_t *list
* @return Returns the entry for the index. Returns NULL if index is out of
bound.
*/
CELIX_UTILS_EXPORT
-celix_array_list_entry_t celix_arrayList_getEntry(const celix_array_list_t
*list, int index);
+celix_array_list_entry_t celix_arrayList_getEntry(const celix_array_list_t*
list, int index);
/**
* @brief add pointer entry to the back of the array list.
@@ -529,14 +535,14 @@ celix_status_t
celix_arrayList_assignVersion(celix_array_list_t* list, celix_ver
* @return The index of the entry or -1 if the entry is not found.
*/
CELIX_UTILS_EXPORT
-int celix_arrayList_indexOf(celix_array_list_t *list, celix_array_list_entry_t
entry);
+int celix_arrayList_indexOf(celix_array_list_t* list, celix_array_list_entry_t
entry);
/**
* @brief Removes an entry at the provided index.
* If the provided index < 0 or out of bound, nothing will be removed.
*/
CELIX_UTILS_EXPORT
-void celix_arrayList_removeAt(celix_array_list_t *list, int index);
+void celix_arrayList_removeAt(celix_array_list_t* list, int index);
/**
* @brief Clear all entries in the array list.
@@ -544,7 +550,7 @@ void celix_arrayList_removeAt(celix_array_list_t *list, int
index);
* @note If a (simple) removed callback is configured, the callback will be
called for every array list entry.
*/
CELIX_UTILS_EXPORT
-void celix_arrayList_clear(celix_array_list_t *list);
+void celix_arrayList_clear(celix_array_list_t* list);
/**
* @brief Remove the first entry from array list which matches the provided
value.
@@ -556,7 +562,7 @@ void celix_arrayList_clear(celix_array_list_t *list);
* If there was no equals callback provided a direct memory compare will be
done.
*/
CELIX_UTILS_EXPORT
-void celix_arrayList_removeEntry(celix_array_list_t *list,
celix_array_list_entry_t entry);
+void celix_arrayList_removeEntry(celix_array_list_t* list,
celix_array_list_entry_t entry);
/**
* @brief Remove the first pointer entry from array list which matches the
provided value.
@@ -634,14 +640,14 @@ void celix_arrayList_removeVersion(celix_array_list_t*
list, const celix_version
* @brief Sort the array list using the provided sort function.
*/
CELIX_UTILS_EXPORT
-void celix_arrayList_sortEntries(celix_array_list_t *list,
celix_array_list_compare_entries_fp compare);
+void celix_arrayList_sortEntries(celix_array_list_t* list,
celix_array_list_compare_entries_fp compare);
/**
* @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_EXPORT
-void celix_arrayList_sort(celix_array_list_t *list);
+void celix_arrayList_sort(celix_array_list_t* list);
/**
* @brief Check if the array list are equal.
diff --git a/libs/utils/src/array_list.c b/libs/utils/src/array_list.c
index 361525f2e..ea49c85ce 100644
--- a/libs/utils/src/array_list.c
+++ b/libs/utils/src/array_list.c
@@ -41,7 +41,7 @@ struct celix_array_list {
celix_array_list_entry_t* elementData;
size_t size;
size_t capacity;
- celix_arrayList_equals_fp equalsCallback;
+ celix_arrayList_equals_fp equalsCallback;
celix_array_list_compare_entries_fp compareCallback;
celix_array_list_copy_entry_fp copyCallback;
void (*simpleRemovedCallback)(void* value);
@@ -101,7 +101,8 @@ static bool
celix_arrayList_versionEquals(celix_array_list_entry_t a, celix_arra
return celix_arrayList_compareVersionEntries(a, b) == 0;
}
-inline static bool celix_arrayList_equalsForElement(celix_array_list_t *list,
celix_array_list_entry_t a, celix_array_list_entry_t b) {
+inline static bool
+celix_arrayList_equalsForElement(celix_array_list_t* list,
celix_array_list_entry_t a, celix_array_list_entry_t b) {
// by class invariant, equalsCallback is never NULL
return list->equalsCallback(a, b);
}
@@ -129,7 +130,7 @@ static void celix_arrayList_destroyVersion(void* v) {
celix_version_destroy(version);
}
-static void celix_arrayList_callRemovedCallback(celix_array_list_t *list, int
index) {
+static void celix_arrayList_callRemovedCallback(celix_array_list_t* list, int
index) {
celix_array_list_entry_t entry = list->elementData[index];
if (list->simpleRemovedCallback != NULL) {
list->simpleRemovedCallback(entry.voidPtrVal);
@@ -139,7 +140,7 @@ static void
celix_arrayList_callRemovedCallback(celix_array_list_t *list, int in
}
static celix_status_t celix_arrayList_ensureCapacity(celix_array_list_t* list,
size_t capacity) {
- celix_array_list_entry_t *newList;
+ celix_array_list_entry_t* newList;
size_t oldCapacity = list->capacity;
if (capacity > oldCapacity) {
size_t newCapacity = (oldCapacity * 3) / 2 + 1;
@@ -192,13 +193,14 @@ static void
celix_arrayList_setTypeSpecificCallbacks(celix_array_list_t* list) {
}
celix_array_list_t* celix_arrayList_createWithOptions(const
celix_array_list_create_options_t* opts) {
- celix_autofree celix_array_list_t *list = calloc(1, sizeof(*list));
+ celix_autofree celix_array_list_t* list = calloc(1, sizeof(*list));
if (!list) {
celix_err_push("Failed to allocate memory for list");
return NULL;
}
- list->capacity = 10;
+ size_t initialCap = opts->initialCapacity > 0 ? opts->initialCapacity : 10;
+ list->capacity = initialCap;
list->elementData = calloc(list->capacity,
sizeof(celix_array_list_entry_t));
if (!list->elementData) {
celix_err_push("Failed to allocate memory for elementData");
@@ -208,7 +210,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 contains callbacks, use them and override the default ones
if (opts->simpleRemovedCallback) {
list->simpleRemovedCallback = opts->simpleRemovedCallback;
}
@@ -262,7 +264,7 @@ celix_array_list_t* celix_arrayList_createVersionArray() {
return
celix_arrayList_createTypedArray(CELIX_ARRAY_LIST_ELEMENT_TYPE_VERSION);
}
-void celix_arrayList_destroy(celix_array_list_t *list) {
+void celix_arrayList_destroy(celix_array_list_t* list) {
if (list != NULL) {
celix_arrayList_clear(list);
free(list->elementData);
@@ -270,15 +272,13 @@ void celix_arrayList_destroy(celix_array_list_t *list) {
}
}
-celix_array_list_element_type_t celix_arrayList_getElementType(const
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;
-}
+int celix_arrayList_size(const celix_array_list_t* list) { return
(int)list->size; }
-static celix_array_list_entry_t arrayList_getEntry(const celix_array_list_t
*list, int index) {
+static celix_array_list_entry_t arrayList_getEntry(const celix_array_list_t*
list, int index) {
celix_array_list_entry_t entry;
memset(&entry, 0, sizeof(entry));
if (index < list->size) {
@@ -287,7 +287,7 @@ static celix_array_list_entry_t arrayList_getEntry(const
celix_array_list_t *lis
return entry;
}
-celix_array_list_entry_t celix_arrayList_getEntry(const celix_array_list_t
*list, int index) {
+celix_array_list_entry_t celix_arrayList_getEntry(const celix_array_list_t*
list, int index) {
return arrayList_getEntry(list, index);
}
@@ -429,11 +429,11 @@ celix_status_t
celix_arrayList_assignVersion(celix_array_list_t* list, celix_ver
return celix_arrayList_addEntry(list, entry);
}
-int celix_arrayList_indexOf(celix_array_list_t *list, celix_array_list_entry_t
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;
int index = -1;
- for (i = 0 ; i < size ; ++i) {
+ for (i = 0; i < size; ++i) {
bool eq = celix_arrayList_equalsForElement(list, entry,
list->elementData[i]);
if (eq) {
index = i;
@@ -442,16 +442,16 @@ int celix_arrayList_indexOf(celix_array_list_t *list,
celix_array_list_entry_t e
}
return index;
}
-void celix_arrayList_removeAt(celix_array_list_t *list, int index) {
+void celix_arrayList_removeAt(celix_array_list_t* list, int index) {
if (index >= 0 && index < list->size) {
celix_arrayList_callRemovedCallback(list, index);
size_t numMoved = list->size - index - 1;
- memmove(list->elementData+index, list->elementData+index+1,
sizeof(celix_array_list_entry_t) * numMoved);
+ memmove(list->elementData + index, list->elementData + index + 1,
sizeof(celix_array_list_entry_t) * numMoved);
memset(&list->elementData[--list->size], 0,
sizeof(celix_array_list_entry_t));
}
}
-void celix_arrayList_removeEntry(celix_array_list_t *list,
celix_array_list_entry_t entry) {
+void celix_arrayList_removeEntry(celix_array_list_t* list,
celix_array_list_entry_t entry) {
int index = celix_arrayList_indexOf(list, entry);
celix_arrayList_removeAt(list, index);
}
@@ -510,7 +510,7 @@ void celix_arrayList_removeVersion(celix_array_list_t*
list, const celix_version
celix_arrayList_removeEntry(list, entry);
}
-void celix_arrayList_clear(celix_array_list_t *list) {
+void celix_arrayList_clear(celix_array_list_t* list) {
for (int i = 0; i < list->size; ++i) {
celix_arrayList_callRemovedCallback(list, i);
memset(&list->elementData[i], 0, sizeof(celix_array_list_entry_t));
@@ -529,7 +529,7 @@ static int celix_arrayList_compareEntries(const void*
voidA, const void* voidB,
return compare(*a, *b);
}
-void celix_arrayList_sort(celix_array_list_t *list) {
+void celix_arrayList_sort(celix_array_list_t* list) {
if (list->compareCallback) {
celix_arrayList_sortEntries(list, list->compareCallback);
}
@@ -592,7 +592,7 @@ celix_array_list_t* celix_arrayList_copy(const
celix_array_list_t* list) {
return NULL;
}
} else {
- entry = list->elementData[i]; //shallow copy
+ entry = list->elementData[i]; // shallow copy
}
(void)celix_arrayList_addEntry(copy, entry); // Cannot fail, because
ensureCapacity is already called to
@@ -602,7 +602,7 @@ celix_array_list_t* celix_arrayList_copy(const
celix_array_list_t* list) {
return celix_steal_ptr(copy);
}
-void celix_arrayList_sortEntries(celix_array_list_t *list,
celix_array_list_compare_entries_fp compare) {
+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);
#else