src/cx/collection.h

changeset 1618
ef7cab6eb131
parent 1605
55b13f583356
--- a/src/cx/collection.h	Tue Dec 16 21:33:58 2025 +0100
+++ b/src/cx/collection.h	Wed Dec 17 19:05:50 2025 +0100
@@ -58,10 +58,6 @@
      */
     const CxAllocator *allocator;
     /**
-     * The comparator function for the elements.
-     */
-    cx_compare_func cmpfunc;
-    /**
      * The size of each element.
      */
     size_t elem_size;
@@ -70,6 +66,19 @@
      */
     size_t size;
     /**
+     * A two-argument comparator function for the elements.
+     */
+    cx_compare_func simple_cmp;
+    /**
+     * A three-argument comparator function for the elements.
+     * If specified, this function has precedence over the @c simple_cmp function.
+     */
+    cx_compare_func2 advanced_cmp;
+    /**
+     * A pointer to custom data for the @c advanced_cmp function
+     */
+    void *cmp_data;
+    /**
      * An optional simple destructor for the collection's elements.
      *
      * @attention Read the documentation of the particular collection implementation
@@ -139,6 +148,25 @@
  */
 #define cxCollectionStoresPointers(c) ((c)->collection.store_pointer)
 
+
+/**
+ * Convenience macro for adding indirection to an element if the collection is storing pointers.
+ *
+ * @param c a pointer to a struct that contains #CX_COLLECTION_BASE
+ * @param elem the pointer that shall be taken the address from, if the collection is storing pointers
+ * @return if the collection is storing pointers, takes the address of @p elem, otherwise returns @p elem
+ */
+#define cx_ref(c, elem) (cxCollectionStoresPointers(c) ? ((void*)&(elem)) : (elem))
+
+/**
+ * Convenience macro for dereferencing an element if the collection is storing pointers.
+ *
+ * @param c a pointer to a struct that contains #CX_COLLECTION_BASE
+ * @param elem a pointer to the collection element
+ * @return if the collection is storing pointers, dereferences @p elem, otherwise returns @p elem
+ */
+#define cx_deref(c, elem) (cxCollectionStoresPointers(c) ? *((void**)(elem)) : (elem))
+
 /**
  * Indicates whether the collection can guarantee that the stored elements are currently sorted.
  *
@@ -154,27 +182,87 @@
 #define cxCollectionSorted(c) ((c)->collection.sorted || (c)->collection.size == 0)
 
 /**
- * Sets the compare function for a collection.
+ * Sets a simple compare function for a collection.
+ *
+ * Erases a possible advanced compare function.
+ * If you want to set both, because you want to access the simple function
+ * in your advanced function, you must set the simple function first.
+ *
+ * @param c a pointer to a struct that contains #CX_COLLECTION_BASE
+ * @param func (@c cx_compare_func) the compare function
+ */
+#define cxSetCompareFunc(c, func) \
+    (c)->collection.simple_cmp = (cx_compare_func)(func); \
+    (c)->collection.advanced_cmp = NULL
+
+/**
+ * Sets an advanced compare function that supports custom data for a collection.
+ *
+ * @param c a pointer to a struct that contains #CX_COLLECTION_BASE
+ * @param func (@c cx_compare_func2) the compare function
+ * @param data (@c void*) the pointer to custom data that is passed to the compare function
+ */
+#define cxSetAdvancedCompareFunc(c, func, data) \
+    (c)->collection.advanced_cmp = (cx_compare_func2) func; \
+    (c)->collection.destructor_data = data
+
+/**
+ * Invokes the simple comparator function for two elements.
+ *
+ * Usually only used by collection implementations. There should be no need
+ * to invoke this macro manually.
  *
  * @param c a pointer to a struct that contains #CX_COLLECTION_BASE
- * @param func (@c cx_compare_func) the compare function that shall be used by @c c
+ * @param left (@c void*) pointer to data
+ * @param right (@c void*) pointer to data
+ */
+#define cx_invoke_simple_compare_func(c, left, right) \
+    (c)->collection.simple_cmp(left, right)
+
+/**
+ * Invokes the advanced comparator function for two elements.
+ *
+ * Usually only used by collection implementations. There should be no need
+ * to invoke this macro manually.
+ *
+ * @param c a pointer to a struct that contains #CX_COLLECTION_BASE
+ * @param left (@c void*) pointer to data
+ * @param right (@c void*) pointer to data
  */
-#define cxSetCompareFunc(c, func) (c)->collection.cmpfunc = (cx_compare_func)(func)
+#define cx_invoke_advanced_compare_func(c, left, right) \
+    (c)->collection.advanced_cmp(left, right, (c)->collection.cmp_data)
+
+
+/**
+ * Invokes the configured comparator function for two elements.
+ *
+ * Usually only used by collection implementations. There should be no need
+ * to invoke this macro manually.
+ *
+ * @param c a pointer to a struct that contains #CX_COLLECTION_BASE
+ * @param left (@c void*) pointer to data
+ * @param right (@c void*) pointer to data
+ */
+#define cx_invoke_compare_func(c, left, right) \
+    (((c)->collection.advanced_cmp) ? \
+    cx_invoke_advanced_compare_func(c,left,right) : \
+    cx_invoke_simple_compare_func(c,left,right))
 
 /**
  * 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
+ * @param destr (@c cx_destructor_func) the destructor function
  */
 #define cxSetDestructor(c, destr) \
     (c)->collection.simple_destructor = (cx_destructor_func) destr
 
 /**
- * Sets a simple destructor function for this collection.
+ * Sets an advanced destructor function for this collection.
  *
  * @param c a pointer to a struct that contains #CX_COLLECTION_BASE
- * @param destr the destructor function
+ * @param destr (@c cx_destructor_func2) the destructor function
+ * @param data (@c void*) the additional data the advanced destructor is invoked with
  */
 #define cxSetAdvancedDestructor(c, destr, data) \
     (c)->collection.advanced_destructor = (cx_destructor_func2) destr; \

mercurial