src/ucx/cx/collection.h

changeset 579
e10457d74fe1
parent 504
c094afcdfb27
--- a/src/ucx/cx/collection.h	Mon Feb 10 17:44:51 2025 +0100
+++ b/src/ucx/cx/collection.h	Sun Mar 02 18:10:52 2025 +0100
@@ -26,12 +26,11 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 /**
- * \file collection.h
- * \brief Common definitions for various collection implementations.
- * \author Mike Becker
- * \author Olaf Wintermann
- * \version 3.0
- * \copyright 2-Clause BSD License
+ * @file collection.h
+ * @brief Common definitions for various collection implementations.
+ * @author Mike Becker
+ * @author Olaf Wintermann
+ * @copyright 2-Clause BSD License
  */
 
 #ifndef UCX_COLLECTION_H
@@ -39,6 +38,7 @@
 
 #include "allocator.h"
 #include "iterator.h"
+#include "compare.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -50,56 +50,125 @@
 #define CX_STORE_POINTERS 0
 
 /**
- * A comparator function comparing two collection elements.
+ * Base attributes of a collection.
  */
-typedef int(*cx_compare_func)(
-        void const *left,
-        void const *right
-);
+struct cx_collection_s {
+    /**
+     * The allocator to use.
+     */
+    const CxAllocator *allocator;
+    /**
+     * The comparator function for the elements.
+     */
+    cx_compare_func cmpfunc;
+    /**
+     * The size of each element.
+     */
+    size_t elem_size;
+    /**
+     * The number of currently stored elements.
+     */
+    size_t size;
+    /**
+     * An optional simple destructor for the collection's elements.
+     *
+     * @attention Read the documentation of the particular collection 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 collection's elements.
+     *
+     * @attention Read the documentation of the particular collection implementation
+     * whether this destructor shall only destroy the contents or also free the memory.
+     */
+    cx_destructor_func2 advanced_destructor;
+    /**
+     * The pointer to additional data that is passed to the advanced destructor.
+     */
+    void *destructor_data;
+    /**
+     * Indicates if this list is supposed to store pointers
+     * instead of copies of the actual objects.
+     */
+    bool store_pointer;
+    /**
+     * Indicates if this collection is guaranteed to be sorted.
+     * Note that the elements can still be sorted, even when the collection is not aware of that.
+     */
+    bool sorted;
+};
 
 /**
  * Use this macro to declare common members for a collection structure.
+ *
+ * @par Example Use
+ * @code
+ * struct MyCustomSet {
+ *     CX_COLLECTION_BASE;
+ *     MySetElements *data;
+ * }
+ * @endcode
  */
-#define CX_COLLECTION_MEMBERS \
-    /** \
-     * The allocator to use. \
-     */ \
-    CxAllocator const *allocator; \
-    /** \
-     * The comparator function for the elements. \
-     */ \
-    cx_compare_func cmpfunc; \
-    /** \
-     * The size of each element. \
-     */ \
-    size_t item_size; \
-    /** \
-     * The number of currently stored elements. \
-     */ \
-    size_t size; \
-    /** \
-     * An optional simple destructor for the collection's elements. \
-     * \
-     * @attention Read the documentation of the particular collection 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 collection's elements. \
-     * \
-     * @attention Read the documentation of the particular collection implementation \
-     * whether this destructor shall only destroy the contents or also free the memory. \
-     */ \
-    cx_destructor_func2 advanced_destructor; \
-    /** \
-     * The pointer to additional data that is passed to the advanced destructor. \
-     */ \
-    void *destructor_data; \
-    /** \
-     * Indicates if this instance of a collection is supposed to store pointers \
-     * instead of copies of the actual objects. \
-     */ \
-    bool store_pointer;
+#define CX_COLLECTION_BASE struct cx_collection_s collection
+
+/**
+ * Returns the number of elements currently stored.
+ *
+ * @param c a pointer to a struct that contains #CX_COLLECTION_BASE
+ * @return (@c size_t) the number of currently stored elements
+ */
+#define cxCollectionSize(c) ((c)->collection.size)
+
+/**
+ * Returns the size of one element.
+ *
+ * If #cxCollectionStoresPointers() returns true, this is the size of a pointer.
+ *
+ * @param c a pointer to a struct that contains #CX_COLLECTION_BASE
+ * @return (@c size_t) the size of one element in bytes
+ */
+#define cxCollectionElementSize(c) ((c)->collection.elem_size)
+
+/**
+ * Indicates whether this collection only stores pointers instead of the actual data.
+ *
+ * @param c a pointer to a struct that contains #CX_COLLECTION_BASE
+ * @retval true if this collection stores only pointers to data
+ * @retval false if this collection stores the actual element's data
+ */
+#define cxCollectionStoresPointers(c) ((c)->collection.store_pointer)
+
+/**
+ * Indicates whether the collection can guarantee that the stored elements are currently sorted.
+ *
+ * This may return false even when the elements are sorted.
+ * It is totally up to the implementation of the collection whether it keeps track of the order of its elements.
+ *
+ * @param c a pointer to a struct that contains #CX_COLLECTION_BASE
+ * @retval true if the elements are currently sorted wrt. the collection's compare function
+ * @retval false if the order of elements is unknown
+ */
+#define cxCollectionSorted(c) ((c)->collection.sorted)
+
+/**
+ * Sets a simple destructor function for this collection.
+ *
+ * @param c a pointer to a struct that contains #CX_COLLECTION_BASE
+ * @param destr the destructor function
+ */
+#define cxDefineDestructor(c, destr) \
+    (c)->collection.simple_destructor = (cx_destructor_func) destr
+
+/**
+ * Sets a simple destructor function for this collection.
+ *
+ * @param c a pointer to a struct that contains #CX_COLLECTION_BASE
+ * @param destr the destructor function
+ */
+#define cxDefineAdvancedDestructor(c, destr, data) \
+    (c)->collection.advanced_destructor = (cx_destructor_func2) destr; \
+    (c)->collection.destructor_data = data
 
 /**
  * Invokes the simple destructor function for a specific element.
@@ -107,11 +176,14 @@
  * Usually only used by collection implementations. There should be no need
  * to invoke this macro manually.
  *
- * @param c the collection
- * @param e the element
+ * When the collection stores pointers, those pointers are directly passed
+ * to the destructor. Otherwise, a pointer to the element is passed.
+ *
+ * @param c a pointer to a struct that contains #CX_COLLECTION_BASE
+ * @param e the element (the type is @c void* or @c void** depending on context)
  */
 #define cx_invoke_simple_destructor(c, e) \
-    (c)->simple_destructor((c)->store_pointer ? (*((void **) (e))) : (e))
+    (c)->collection.simple_destructor((c)->collection.store_pointer ? (*((void **) (e))) : (e))
 
 /**
  * Invokes the advanced destructor function for a specific element.
@@ -119,12 +191,15 @@
  * Usually only used by collection implementations. There should be no need
  * to invoke this macro manually.
  *
- * @param c the collection
- * @param e the element
+ * When the collection stores pointers, those pointers are directly passed
+ * to the destructor. Otherwise, a pointer to the element is passed.
+ *
+ * @param c a pointer to a struct that contains #CX_COLLECTION_BASE
+ * @param e the element (the type is @c void* or @c void** depending on context)
  */
 #define cx_invoke_advanced_destructor(c, e) \
-    (c)->advanced_destructor((c)->destructor_data, \
-    (c)->store_pointer ? (*((void **) (e))) : (e))
+    (c)->collection.advanced_destructor((c)->collection.destructor_data, \
+    (c)->collection.store_pointer ? (*((void **) (e))) : (e))
 
 
 /**
@@ -133,12 +208,15 @@
  * Usually only used by collection implementations. There should be no need
  * to invoke this macro manually.
  *
- * @param c the collection
- * @param e the element
+ * When the collection stores pointers, those pointers are directly passed
+ * to the destructor. Otherwise, a pointer to the element is passed.
+ *
+ * @param c a pointer to a struct that contains #CX_COLLECTION_BASE
+ * @param e the element (the type is @c void* or @c void** depending on context)
  */
 #define cx_invoke_destructor(c, e) \
-    if ((c)->simple_destructor) cx_invoke_simple_destructor(c,e); \
-    if ((c)->advanced_destructor) cx_invoke_advanced_destructor(c,e)
+    if ((c)->collection.simple_destructor) cx_invoke_simple_destructor(c,e); \
+    if ((c)->collection.advanced_destructor) cx_invoke_advanced_destructor(c,e)
 
 #ifdef __cplusplus
 } // extern "C"

mercurial