remove API for changing the store_pointer property after list creation

Mon, 06 Jan 2025 23:29:41 +0100

author
Mike Becker <universe@uap-core.de>
date
Mon, 06 Jan 2025 23:29:41 +0100
changeset 1111
78eeeb950883
parent 1110
a0e9be7ed131
child 1112
22dc2163fffd

remove API for changing the store_pointer property after list creation

fixes #553

CHANGELOG file | annotate | diff | comparison | revisions
src/array_list.c file | annotate | diff | comparison | revisions
src/cx/array_list.h file | annotate | diff | comparison | revisions
src/cx/hash_map.h file | annotate | diff | comparison | revisions
src/cx/linked_list.h file | annotate | diff | comparison | revisions
src/cx/list.h file | annotate | diff | comparison | revisions
src/cx/map.h file | annotate | diff | comparison | revisions
src/hash_map.c file | annotate | diff | comparison | revisions
src/linked_list.c file | annotate | diff | comparison | revisions
src/list.c file | annotate | diff | comparison | revisions
tests/test_hash_map.c file | annotate | diff | comparison | revisions
tests/test_list.c file | annotate | diff | comparison | revisions
--- a/CHANGELOG	Sun Jan 05 18:19:42 2025 +0100
+++ b/CHANGELOG	Mon Jan 06 23:29:41 2025 +0100
@@ -32,6 +32,7 @@
  * removes utils.h
  * removes flag_removal function from iterator
  * removes cxMapDetach() and makes cxMapRemoveAndGet() compatible with both map variants
+ * removes the API for changing the store_pointer property of collections after their creation
  * removes CMake
  * removes GTest dependency
  * removes flags to disable SBO in tests
--- a/src/array_list.c	Sun Jan 05 18:19:42 2025 +0100
+++ b/src/array_list.c	Mon Jan 06 23:29:41 2025 +0100
@@ -1013,22 +1013,13 @@
 
     cx_array_list *list = cxCalloc(allocator, 1, sizeof(cx_array_list));
     if (list == NULL) return NULL;
-
-    list->base.cl = &cx_array_list_class;
-    list->base.collection.allocator = allocator;
+    cx_list_init((CxList*)list, &cx_array_list_class,
+        allocator, comparator, elem_size);
     list->capacity = initial_capacity;
 
-    if (elem_size > 0) {
-        list->base.collection.elem_size = elem_size;
-        list->base.collection.cmpfunc = comparator;
-    } else {
-        elem_size = sizeof(void *);
-        list->base.collection.cmpfunc = comparator == NULL ? cx_cmp_ptr : comparator;
-        cxListStorePointers((CxList *) list);
-    }
-
     // allocate the array after the real elem_size is known
-    list->data = cxCalloc(allocator, initial_capacity, elem_size);
+    list->data = cxCalloc(allocator, initial_capacity,
+        list->base.collection.elem_size);
     if (list->data == NULL) { // LCOV_EXCL_START
         cxFree(allocator, list);
         return NULL;
--- a/src/cx/array_list.h	Sun Jan 05 18:19:42 2025 +0100
+++ b/src/cx/array_list.h	Mon Jan 06 23:29:41 2025 +0100
@@ -684,9 +684,9 @@
 /**
  * Allocates an array list for storing elements with @p elem_size bytes each.
  *
- * If @p elem_size is CX_STORE_POINTERS, the created list will be created as if
- * cxListStorePointers() was called immediately after creation and the compare
- * function will be automatically set to cx_cmp_ptr(), if none is given.
+ * If @p elem_size is #CX_STORE_POINTERS, the created list stores pointers instead of
+ * copies of the added elements and the compare function will be automatically set
+ * to cx_cmp_ptr(), if none is given.
  *
  * @param allocator the allocator for allocating the list memory
  * (if @c NULL, a default stdlib allocator will be used)
@@ -714,9 +714,9 @@
  * If you want to call functions that need a compare function, you have to
  * set it immediately after creation or use cxArrayListCreate().
  *
- * If @p elem_size is CX_STORE_POINTERS, the created list will be created as if
- * cxListStorePointers() was called immediately after creation and the compare
- * function will be automatically set to cx_cmp_ptr().
+ * If @p elem_size is #CX_STORE_POINTERS, the created list stores pointers instead of
+ * copies of the added elements and the compare function will be automatically set
+ * to cx_cmp_ptr(), if none is given.
  *
  * @param elem_size (@c size_t) the size of each element in bytes
  * @param initial_capacity (@c size_t) the initial number of elements the array can store
--- a/src/cx/hash_map.h	Sun Jan 05 18:19:42 2025 +0100
+++ b/src/cx/hash_map.h	Mon Jan 06 23:29:41 2025 +0100
@@ -69,8 +69,8 @@
  *
  * If @p buckets is zero, an implementation defined default will be used.
  *
- * If @p elem_size is CX_STORE_POINTERS, the created map will be created as if
- * cxMapStorePointers() was called immediately after creation.
+ * If @p elem_size is #CX_STORE_POINTERS, the created map stores pointers instead of
+ * copies of the added elements.
  *
  * @note Iterators provided by this hash map implementation provide the remove operation.
  * The index value of an iterator is incremented when the iterator advanced without removal.
@@ -94,8 +94,8 @@
 /**
  * Creates a new hash map with a default number of buckets.
  *
- * If @p elem_size is CX_STORE_POINTERS, the created map will be created as if
- * cxMapStorePointers() was called immediately after creation.
+ * If @p elem_size is #CX_STORE_POINTERS, the created map stores pointers instead of
+ * copies of the added elements.
  *
  * @note Iterators provided by this hash map implementation provide the remove operation.
  * The index value of an iterator is incremented when the iterator advanced without removal.
--- a/src/cx/linked_list.h	Sun Jan 05 18:19:42 2025 +0100
+++ b/src/cx/linked_list.h	Mon Jan 06 23:29:41 2025 +0100
@@ -52,9 +52,9 @@
 /**
  * Allocates a linked list for storing elements with @p elem_size bytes each.
  *
- * If @p elem_size is CX_STORE_POINTERS, the created list will be created as if
- * cxListStorePointers() was called immediately after creation and the compare
- * function will be automatically set to cx_cmp_ptr(), if none is given.
+ * If @p elem_size is #CX_STORE_POINTERS, the created list stores pointers instead of
+ * copies of the added elements and the compare function will be automatically set
+ * to cx_cmp_ptr(), if none is given.
  *
  * @param allocator the allocator for allocating the list nodes
  * (if @c NULL, a default stdlib allocator will be used)
@@ -80,9 +80,9 @@
  * to call functions that need a comparator, you must either set one immediately
  * after list creation or use cxLinkedListCreate().
  *
- * If @p elem_size is CX_STORE_POINTERS, the created list will be created as if
- * cxListStorePointers() was called immediately after creation and the compare
- * function will be automatically set to cx_cmp_ptr().
+ * If @p elem_size is #CX_STORE_POINTERS, the created list stores pointers instead of
+ * copies of the added elements and the compare function will be automatically set
+ * to cx_cmp_ptr(), if none is given.
  *
  * @param elem_size (@c size_t) the size of each element in bytes
  * @return (@c CxList*) the created list
--- a/src/cx/list.h	Sun Jan 05 18:19:42 2025 +0100
+++ b/src/cx/list.h	Mon Jan 06 23:29:41 2025 +0100
@@ -280,50 +280,64 @@
 int cx_list_default_swap(struct cx_list_s *list, size_t i, size_t j);
 
 /**
+ * Initializes a list struct.
+ *
+ * Only use this function if you are creating your own list implementation.
+ * The purpose of this function is to be called in the initialization code
+ * of your list, to set certain members correctly.
+ *
+ * This is particularly important when you want your list to support
+ * #CX_STORE_POINTERS as @p elem_size. This function will wrap the list
+ * class accordingly and make sure that you can implement your list as if
+ * it was only storing objects and the wrapper will automatically enable
+ * the feature of storing pointers.
+ *
+ * @par Example
+ *
+ * @code
+ * CxList *myCustomListCreate(
+ *         const CxAllocator *allocator,
+ *         cx_compare_func comparator,
+ *         size_t elem_size
+ * ) {
+ *     if (allocator == NULL) {
+ *         allocator = cxDefaultAllocator;
+ *     }
+ *
+ *     MyCustomList *list = cxCalloc(allocator, 1, sizeof(MyCustomList));
+ *     if (list == NULL) return NULL;
+ *
+ *     // initialize
+ *     cx_list_init((CxList*)list, &my_custom_list_class,
+ *             allocator, comparator, elem_size);
+ *
+ *     // ... some more custom stuff ...
+ *
+ *     return (CxList *) list;
+ * }
+ * @endcode
+ *
+ * @param list the list to initialize
+ * @param cl the list class
+ * @param allocator the allocator for the elements
+ * @param comparator a compare function for the elements
+ * @param elem_size the size of one element
+ */
+cx_attr_nonnull_arg(1, 2, 3)
+void cx_list_init(
+    struct cx_list_s *list,
+    struct cx_list_class_s *cl,
+    const struct cx_allocator_s *allocator,
+    cx_compare_func comparator,
+    size_t elem_size
+);
+
+/**
  * Common type for all list implementations.
  */
 typedef struct cx_list_s CxList;
 
 /**
- * Advises the list to store copies of the objects (default mode of operation).
- *
- * Retrieving objects from this list will yield pointers to the copies stored
- * within this list.
- *
- * @param list the list
- * @see cxListStorePointers()
- */
-cx_attr_nonnull
-void cxListStoreObjects(CxList *list);
-
-/**
- * Advises the list to only store pointers to the objects.
- *
- * Retrieving objects from this list will yield the original pointers stored.
- *
- * @note This function forcibly sets the element size to the size of a pointer.
- * Invoking this function on a non-empty list that already stores copies of
- * objects is undefined.
- *
- * @param list the list
- * @see cxListStoreObjects()
- */
-cx_attr_nonnull
-void cxListStorePointers(CxList *list);
-
-/**
- * Returns true, if this list is storing pointers instead of the actual data.
- *
- * @param list
- * @return true, if this list is storing pointers
- * @see cxListStorePointers()
- */
-cx_attr_nonnull
-static inline bool cxListIsStoringPointers(const CxList *list) {
-    return list->collection.store_pointer;
-}
-
-/**
  * Returns the number of elements currently stored in the list.
  *
  * @param list the list
--- a/src/cx/map.h	Sun Jan 05 18:19:42 2025 +0100
+++ b/src/cx/map.h	Mon Jan 06 23:29:41 2025 +0100
@@ -160,50 +160,6 @@
 extern CxMap *const cxEmptyMap;
 
 /**
- * Advises the map to store copies of the objects (default mode of operation).
- *
- * Retrieving objects from this map will yield pointers to the copies stored
- * within this list.
- *
- * @param map the map
- * @see cxMapStorePointers()
- */
-cx_attr_nonnull
-static inline void cxMapStoreObjects(CxMap *map) {
-    map->collection.store_pointer = false;
-}
-
-/**
- * Advises the map to only store pointers to the objects.
- *
- * Retrieving objects from this list will yield the original pointers stored.
- *
- * @note This function forcibly sets the element size to the size of a pointer.
- * Invoking this function on a non-empty map that already stores copies of
- * objects is undefined.
- *
- * @param map the map
- * @see cxMapStoreObjects()
- */
-cx_attr_nonnull
-static inline void cxMapStorePointers(CxMap *map) {
-    map->collection.store_pointer = true;
-    map->collection.elem_size = sizeof(void *);
-}
-
-/**
- * Returns true, if this map is storing pointers instead of the actual data.
- *
- * @param map
- * @return true, if this map is storing pointers
- * @see cxMapStorePointers()
- */
-cx_attr_nonnull
-static inline bool cxMapIsStoringPointers(const CxMap *map) {
-    return map->collection.store_pointer;
-}
-
-/**
  * Deallocates the memory of the specified map.
  *
  * Also calls the content destructor functions for each element, if specified.
@@ -761,8 +717,7 @@
  * @param targetbuf (@c void*) the buffer where the element shall be copied to
  * @retval zero success
  * @retval non-zero the key was not found
- * 
- * @see cxMapStorePointers()
+ *
  * @see cxMapRemove()
  */
 #define cxMapRemoveAndGet(map, key, targetbuf) _Generic((key), \
--- a/src/hash_map.c	Sun Jan 05 18:19:42 2025 +0100
+++ b/src/hash_map.c	Mon Jan 06 23:29:41 2025 +0100
@@ -433,11 +433,10 @@
     map->base.collection.allocator = allocator;
 
     if (itemsize > 0) {
-        map->base.collection.store_pointer = false;
         map->base.collection.elem_size = itemsize;
     } else {
+        map->base.collection.elem_size = sizeof(void *);
         map->base.collection.store_pointer = true;
-        map->base.collection.elem_size = sizeof(void *);
     }
 
     return (CxMap *) map;
--- a/src/linked_list.c	Sun Jan 05 18:19:42 2025 +0100
+++ b/src/linked_list.c	Mon Jan 06 23:29:41 2025 +0100
@@ -1138,17 +1138,8 @@
 
     cx_linked_list *list = cxCalloc(allocator, 1, sizeof(cx_linked_list));
     if (list == NULL) return NULL;
-
-    list->base.cl = &cx_linked_list_class;
-    list->base.collection.allocator = allocator;
-
-    if (elem_size > 0) {
-        list->base.collection.elem_size = elem_size;
-        list->base.collection.cmpfunc = comparator;
-    } else {
-        list->base.collection.cmpfunc = comparator == NULL ? cx_cmp_ptr : comparator;
-        cxListStorePointers((CxList *) list);
-    }
+    cx_list_init((CxList*)list, &cx_linked_list_class,
+            allocator, comparator, elem_size);
 
     return (CxList *) list;
 }
--- a/src/list.c	Sun Jan 05 18:19:42 2025 +0100
+++ b/src/list.c	Mon Jan 06 23:29:41 2025 +0100
@@ -192,22 +192,6 @@
         cx_pl_reverse,
         cx_pl_iterator,
 };
-
-void cxListStoreObjects(CxList *list) {
-    list->collection.store_pointer = false;
-    if (list->climpl != NULL) {
-        list->cl = list->climpl;
-        list->climpl = NULL;
-    }
-}
-
-void cxListStorePointers(CxList *list) {
-    list->collection.elem_size = sizeof(void *);
-    list->collection.store_pointer = true;
-    list->climpl = list->cl;
-    list->cl = &cx_pointer_list_class;
-}
-
 // </editor-fold>
 
 // <editor-fold desc="empty list implementation">
@@ -417,6 +401,29 @@
     return 0;
 }
 
+void cx_list_init(
+    struct cx_list_s *list,
+    struct cx_list_class_s *cl,
+    const struct cx_allocator_s *allocator,
+    cx_compare_func comparator,
+    size_t elem_size
+) {
+    list->cl = cl;
+    list->collection.allocator = allocator;
+    list->collection.cmpfunc = comparator;
+    if (elem_size > 0) {
+        list->collection.elem_size = elem_size;
+    } else {
+        list->collection.elem_size = sizeof(void *);
+        if (list->collection.cmpfunc == NULL) {
+            list->collection.cmpfunc = cx_cmp_ptr;
+        }
+        list->collection.store_pointer = true;
+        list->climpl = list->cl;
+        list->cl = &cx_pointer_list_class;
+    }
+}
+
 int cxListCompare(
         const CxList *list,
         const CxList *other
--- a/tests/test_hash_map.c	Sun Jan 05 18:19:42 2025 +0100
+++ b/tests/test_hash_map.c	Mon Jan 06 23:29:41 2025 +0100
@@ -50,11 +50,6 @@
         CX_TEST_ASSERT(map->collection.simple_destructor == NULL);
         CX_TEST_ASSERT(map->collection.advanced_destructor == NULL);
         CX_TEST_ASSERT(map->collection.destructor_data == NULL);
-        cxMapStorePointers(map);
-        CX_TEST_ASSERT(map->collection.store_pointer);
-        CX_TEST_ASSERT(map->collection.elem_size == sizeof(void *));
-        cxMapStoreObjects(map);
-        CX_TEST_ASSERT(!map->collection.store_pointer);
 
         cxMapFree(map);
         CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc));
--- a/tests/test_list.c	Sun Jan 05 18:19:42 2025 +0100
+++ b/tests/test_list.c	Mon Jan 06 23:29:41 2025 +0100
@@ -1010,7 +1010,7 @@
         CX_TEST_ASSERT(cxListSize(list) == 0);
         CX_TEST_ASSERT(list->collection.allocator == alloc);
         CX_TEST_ASSERT(list->collection.cmpfunc == cx_cmp_int);
-        CX_TEST_ASSERT(!cxListIsStoringPointers(list));
+        CX_TEST_ASSERT(!list->collection.store_pointer);
         cxListFree(list);
         CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc));
     }
@@ -1028,24 +1028,7 @@
         CX_TEST_ASSERT(cxListSize(list) == 0);
         CX_TEST_ASSERT(list->collection.allocator == cxDefaultAllocator);
         CX_TEST_ASSERT(list->collection.cmpfunc == NULL);
-        CX_TEST_ASSERT(!cxListIsStoringPointers(list));
-    }
-    cxListFree(list);
-}
-
-CX_TEST(test_list_ll_store_pointers) {
-    CxList *list = cxLinkedListCreateSimple(47);
-    CX_TEST_DO {
-        CX_TEST_ASSERT(!cxListIsStoringPointers(list));
-        cxListStorePointers(list);
-        CX_TEST_ASSERT(list->collection.elem_size == sizeof(void *));
-        CX_TEST_ASSERT(list->cl != NULL);
-        CX_TEST_ASSERT(list->climpl != NULL);
-        CX_TEST_ASSERT(cxListIsStoringPointers(list));
-        cxListStoreObjects(list);
-        CX_TEST_ASSERT(list->cl != NULL);
-        CX_TEST_ASSERT(list->climpl == NULL);
-        CX_TEST_ASSERT(!cxListIsStoringPointers(list));
+        CX_TEST_ASSERT(!list->collection.store_pointer);
     }
     cxListFree(list);
 }
@@ -1061,7 +1044,7 @@
         CX_TEST_ASSERT(cxListSize(list) == 0);
         CX_TEST_ASSERT(list->collection.allocator == cxDefaultAllocator);
         CX_TEST_ASSERT(list->collection.cmpfunc == cx_cmp_ptr);
-        CX_TEST_ASSERT(cxListIsStoringPointers(list));
+        CX_TEST_ASSERT(list->collection.store_pointer);
     }
     cxListFree(list);
 }
@@ -1080,7 +1063,7 @@
         CX_TEST_ASSERT(cxListSize(list) == 0);
         CX_TEST_ASSERT(list->collection.allocator == alloc);
         CX_TEST_ASSERT(list->collection.cmpfunc == cx_cmp_int);
-        CX_TEST_ASSERT(!cxListIsStoringPointers(list));
+        CX_TEST_ASSERT(!list->collection.store_pointer);
         cxListFree(list);
         CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc));
     }
@@ -1098,7 +1081,7 @@
         CX_TEST_ASSERT(cxListSize(list) == 0);
         CX_TEST_ASSERT(list->collection.allocator == cxDefaultAllocator);
         CX_TEST_ASSERT(list->collection.cmpfunc == NULL);
-        CX_TEST_ASSERT(!cxListIsStoringPointers(list));
+        CX_TEST_ASSERT(!list->collection.store_pointer);
     }
     cxListFree(list);
 }
@@ -1114,7 +1097,7 @@
         CX_TEST_ASSERT(cxListSize(list) == 0);
         CX_TEST_ASSERT(list->collection.allocator == cxDefaultAllocator);
         CX_TEST_ASSERT(list->collection.cmpfunc == cx_cmp_ptr);
-        CX_TEST_ASSERT(cxListIsStoringPointers(list));
+        CX_TEST_ASSERT(list->collection.store_pointer);
     }
     cxListFree(list);
 }
@@ -1862,7 +1845,7 @@
                           const int *testdata, size_t testdata_len) {
     destr_test_ctr = 0;
     
-    int off = cxListIsStoringPointers(list) ? 1 : 0;
+    int off = list->collection.store_pointer ? 1 : 0;
 
     cxListRemove(list, 15);
     CX_TEST_ASSERT(1 == destr_test_ctr);
@@ -2025,7 +2008,6 @@
 
     cx_test_register(suite, test_list_ll_create);
     cx_test_register(suite, test_list_ll_create_simple);
-    cx_test_register(suite, test_list_ll_store_pointers);
     cx_test_register(suite, test_list_ll_create_simple_for_pointers);
     cx_test_register(suite, test_list_pll_destroy_no_destr);
     cx_test_register(suite, test_list_pll_destroy_simple_destr);

mercurial