src/ucx/cx/list.h

changeset 490
d218607f5a7e
parent 438
22eca559aded
child 504
c094afcdfb27
--- a/src/ucx/cx/list.h	Sat Mar 25 17:18:51 2023 +0100
+++ b/src/ucx/cx/list.h	Fri May 05 18:02:11 2023 +0200
@@ -38,22 +38,13 @@
 #define UCX_LIST_H
 
 #include "common.h"
-#include "allocator.h"
-#include "iterator.h"
+#include "collection.h"
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 /**
- * A comparator function comparing two list elements.
- */
-typedef int(*CxListComparator)(
-        void const *left,
-        void const *right
-);
-
-/**
  * List class type.
  */
 typedef struct cx_list_class_s cx_list_class;
@@ -62,54 +53,15 @@
  * Structure for holding the base data of a list.
  */
 struct cx_list_s {
+    CX_COLLECTION_MEMBERS
     /**
      * The list class definition.
      */
-    cx_list_class *cl;
-    /**
-     * The allocator to use.
-     */
-    CxAllocator const *allocator;
-    /**
-     * The comparator function for the elements.
-     */
-    CxListComparator cmpfunc;
+    cx_list_class const *cl;
     /**
-     * The size of each element (payload only).
-     */
-    size_t itemsize;
-    /**
-     * The size of the list (number of currently stored elements).
-     */
-    size_t size;
-    /**
-     * The capacity of the list (maximum number of elements).
+     * The actual implementation in case the list class is delegating.
      */
-    size_t capacity;
-    union {
-        /**
-         * An optional simple destructor for the list contents that admits the free() interface.
-         *
-         * @remark Set content_destructor_type to #CX_DESTRUCTOR_SIMPLE.
-         *
-         * @attention Read the documentation of the particular list implementation
-         * whether this destructor shall only destroy the contents or also free the memory.
-         */
-        cx_destructor_func simple_destructor;
-        /**
-         * An optional advanced destructor for the list contents providing additional data.
-         *
-         * @remark Set content_destructor_type to #CX_DESTRUCTOR_ADVANCED.
-         *
-         * @attention Read the documentation of the particular list implementation
-         * whether this destructor shall only destroy the contents or also free the memory.
-         */
-        cx_advanced_destructor advanced_destructor;
-    };
-    /**
-     * The type of destructor to use.
-     */
-    enum cx_destructor_type content_destructor_type;
+    cx_list_class const *climpl;
 };
 
 /**
@@ -122,29 +74,24 @@
     void (*destructor)(struct cx_list_s *list);
 
     /**
-     * Member function for adding an element.
+     * Member function for inserting a single elements.
+     * Implementors SHOULD see to performant implementations for corner cases.
      */
-    int (*add)(
+    int (*insert_element)(
             struct cx_list_s *list,
-            void const *elem
+            size_t index,
+            void const *data
     );
 
     /**
-     * Member function for adding multiple elements.
+     * Member function for inserting multiple elements.
+     * Implementors SHOULD see to performant implementations for corner cases.
      */
-    size_t (*add_array)(
-            struct cx_list_s *list,
-            void const *array,
-            size_t n
-    );
-
-    /**
-     * Member function for inserting an element.
-     */
-    int (*insert)(
+    size_t (*insert_array)(
             struct cx_list_s *list,
             size_t index,
-            void const *elem
+            void const *data,
+            size_t n
     );
 
     /**
@@ -165,6 +112,20 @@
     );
 
     /**
+     * Member function for removing all elements.
+     */
+    void (*clear)(struct cx_list_s *list);
+
+    /**
+     * Member function for swapping two elements.
+     */
+    int (*swap)(
+            struct cx_list_s *list,
+            size_t i,
+            size_t j
+    );
+
+    /**
      * Member function for element lookup.
      */
     void *(*at)(
@@ -175,7 +136,7 @@
     /**
      * Member function for finding an element.
      */
-    size_t (*find)(
+    ssize_t (*find)(
             struct cx_list_s const *list,
             void const *elem
     );
@@ -199,19 +160,12 @@
     void (*reverse)(struct cx_list_s *list);
 
     /**
-     * Returns an iterator pointing to the specified index.
+     * Member function for returning an iterator pointing to the specified index.
      */
     struct cx_iterator_s (*iterator)(
             struct cx_list_s const *list,
-            size_t index
-    );
-
-    /**
-     * Returns a mutating iterator pointing to the specified index.
-     */
-    struct cx_mut_iterator_s (*mut_iterator)(
-            struct cx_list_s *list,
-            size_t index
+            size_t index,
+            bool backward
     );
 };
 
@@ -221,6 +175,56 @@
 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()
+ */
+__attribute__((__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()
+ */
+__attribute__((__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()
+ */
+__attribute__((__nonnull__))
+static inline bool cxListIsStoringPointers(CxList const *list) {
+    return list->store_pointer;
+}
+
+/**
+ * Returns the number of elements currently stored in the list.
+ *
+ * @param list the list
+ * @return the number of currently stored elements
+ */
+__attribute__((__nonnull__))
+static inline size_t cxListSize(CxList const *list) {
+    return list->size;
+}
+
+/**
  * Adds an item to the end of the list.
  *
  * @param list the list
@@ -233,7 +237,7 @@
         CxList *list,
         void const *elem
 ) {
-    return list->cl->add(list, elem);
+    return list->cl->insert_element(list, list->size, elem);
 }
 
 /**
@@ -244,6 +248,9 @@
  * If there is not enough memory to add all elements, the returned value is
  * less than \p n.
  *
+ * If this list is storing pointers instead of objects \p array is expected to
+ * be an array of pointers.
+ *
  * @param list the list
  * @param array a pointer to the elements to add
  * @param n the number of elements to add
@@ -255,7 +262,7 @@
         void const *array,
         size_t n
 ) {
-    return list->cl->add_array(list, array, n);
+    return list->cl->insert_array(list, list->size, array, n);
 }
 
 /**
@@ -277,7 +284,36 @@
         size_t index,
         void const *elem
 ) {
-    return list->cl->insert(list, index, elem);
+    return list->cl->insert_element(list, index, elem);
+}
+
+/**
+ * Inserts multiple items to the list at the specified index.
+ * If \p index equals the list size, this is effectively cxListAddArray().
+ *
+ * This method is usually more efficient than invoking cxListInsert()
+ * multiple times.
+ *
+ * If there is not enough memory to add all elements, the returned value is
+ * less than \p n.
+ *
+ * If this list is storing pointers instead of objects \p array is expected to
+ * be an array of pointers.
+ *
+ * @param list the list
+ * @param index the index where to add the elements
+ * @param array a pointer to the elements to add
+ * @param n the number of elements to add
+ * @return the number of added elements
+ */
+__attribute__((__nonnull__))
+static inline size_t cxListInsertArray(
+        CxList *list,
+        size_t index,
+        void const *array,
+        size_t n
+) {
+    return list->cl->insert_array(list, index, array, n);
 }
 
 /**
@@ -328,6 +364,10 @@
 
 /**
  * Removes the element at the specified index.
+ *
+ * If an element destructor function is specified, it is called before
+ * removing the element.
+ *
  * @param list the list
  * @param index the index of the element
  * @return zero on success, non-zero if the index is out of bounds
@@ -341,6 +381,39 @@
 }
 
 /**
+ * Removes all elements from this list.
+ *
+ * If an element destructor function is specified, it is called for each
+ * element before removing them.
+ *
+ * @param list the list
+ */
+__attribute__((__nonnull__))
+static inline void cxListClear(CxList *list) {
+    list->cl->clear(list);
+}
+
+/**
+ * Swaps two items in the list.
+ *
+ * Implementations should only allocate temporary memory for the swap, if
+ * it is necessary.
+ *
+ * @param list the list
+ * @param i the index of the first element
+ * @param j the index of the second element
+ * @return zero on success, non-zero if one of the indices is out of bounds
+ */
+__attribute__((__nonnull__))
+static inline int cxListSwap(
+        CxList *list,
+        size_t i,
+        size_t j
+) {
+    return list->cl->swap(list, i, j);
+}
+
+/**
  * Returns a pointer to the element at the specified index.
  *
  * @param list the list
@@ -367,11 +440,30 @@
  * @return a new iterator
  */
 __attribute__((__nonnull__, __warn_unused_result__))
-static inline CxIterator cxListIterator(
+static inline CxIterator cxListIteratorAt(
         CxList const *list,
         size_t index
 ) {
-    return list->cl->iterator(list, index);
+    return list->cl->iterator(list, index, false);
+}
+
+/**
+ * Returns a backwards iterator pointing to the item at the specified index.
+ *
+ * The returned iterator is position-aware.
+ *
+ * If the index is out of range, a past-the-end iterator will be returned.
+ *
+ * @param list the list
+ * @param index the index where the iterator shall point at
+ * @return a new iterator
+ */
+__attribute__((__nonnull__, __warn_unused_result__))
+static inline CxIterator cxListBackwardsIteratorAt(
+        CxList const *list,
+        size_t index
+) {
+    return list->cl->iterator(list, index, true);
 }
 
 /**
@@ -386,12 +478,28 @@
  * @return a new iterator
  */
 __attribute__((__nonnull__, __warn_unused_result__))
-static inline CxMutIterator cxListMutIterator(
+CxMutIterator cxListMutIteratorAt(
         CxList *list,
         size_t index
-) {
-    return list->cl->mut_iterator(list, index);
-}
+);
+
+/**
+ * Returns a mutating backwards iterator pointing to the item at the
+ * specified index.
+ *
+ * The returned iterator is position-aware.
+ *
+ * If the index is out of range, a past-the-end iterator will be returned.
+ *
+ * @param list the list
+ * @param index the index where the iterator shall point at
+ * @return a new iterator
+ */
+__attribute__((__nonnull__, __warn_unused_result__))
+CxMutIterator cxListMutBackwardsIteratorAt(
+        CxList *list,
+        size_t index
+);
 
 /**
  * Returns an iterator pointing to the first item of the list.
@@ -404,8 +512,8 @@
  * @return a new iterator
  */
 __attribute__((__nonnull__, __warn_unused_result__))
-static inline CxIterator cxListBegin(CxList const *list) {
-    return list->cl->iterator(list, 0);
+static inline CxIterator cxListIterator(CxList const *list) {
+    return list->cl->iterator(list, 0, false);
 }
 
 /**
@@ -419,8 +527,39 @@
  * @return a new iterator
  */
 __attribute__((__nonnull__, __warn_unused_result__))
-static inline CxMutIterator cxListBeginMut(CxList *list) {
-    return list->cl->mut_iterator(list, 0);
+static inline CxMutIterator cxListMutIterator(CxList *list) {
+    return cxListMutIteratorAt(list, 0);
+}
+
+
+/**
+ * Returns a backwards iterator pointing to the last item of the list.
+ *
+ * The returned iterator is position-aware.
+ *
+ * If the list is empty, a past-the-end iterator will be returned.
+ *
+ * @param list the list
+ * @return a new iterator
+ */
+__attribute__((__nonnull__, __warn_unused_result__))
+static inline CxIterator cxListBackwardsIterator(CxList const *list) {
+    return list->cl->iterator(list, list->size - 1, true);
+}
+
+/**
+ * Returns a mutating backwards iterator pointing to the last item of the list.
+ *
+ * The returned iterator is position-aware.
+ *
+ * If the list is empty, a past-the-end iterator will be returned.
+ *
+ * @param list the list
+ * @return a new iterator
+ */
+__attribute__((__nonnull__, __warn_unused_result__))
+static inline CxMutIterator cxListMutBackwardsIterator(CxList *list) {
+    return cxListMutBackwardsIteratorAt(list, list->size - 1);
 }
 
 /**
@@ -430,10 +569,11 @@
  *
  * @param list the list
  * @param elem the element to find
- * @return the index of the element or \c (size+1) if the element is not found
+ * @return the index of the element or a negative
+ * value when the element is not found
  */
 __attribute__((__nonnull__))
-static inline size_t cxListFind(
+static inline ssize_t cxListFind(
         CxList const *list,
         void const *elem
 ) {

mercurial