diff -r d4385f35f8b0 -r ef7cab6eb131 docs/Writerside/topics/collection.h.md --- a/docs/Writerside/topics/collection.h.md Tue Dec 16 21:33:58 2025 +0100 +++ b/docs/Writerside/topics/collection.h.md Wed Dec 17 19:05:50 2025 +0100 @@ -21,17 +21,19 @@ The following attributes are declared by the `CX_COLLECTION_BASE` macro: -| Attribute | Description | -|-----------------------|----------------------------------------------------------------------------------------------------------------| -| `allocator` | The [allocator](allocator.h.md) that shall be used for the collection data. | -| `cmpfunc` | A function to [compare](compare.h.md) two elements. | -| `elem_size` | The size of one element in bytes. | -| `size` | The size, meaning the number of elements, currently stored. | -| `simple_destructor` | An optional simple [destructor function](allocator.h.md#destructor-functions). | -| `advanced_destructor` | An optional advanced destructor function. | -| `destructor_data` | A pointer to the custom data that shall be passed to the advanced destructor. | -| `store_pointer` | A `bool` indicating whether this collection stores pointers instead of the element's data. | -| `sorted` | A `bool` indicating whether the elements are currently guaranteed sorted with respect to the compare function. | +| Attribute | Description | +|-----------------------|-----------------------------------------------------------------------------------------------------------------------------------| +| `allocator` | The [allocator](allocator.h.md) that shall be used for the collection data. | +| `elem_size` | The size of one element in bytes. | +| `size` | The size, meaning the number of elements, currently stored. | +| `simple_cmp` | A function to [compare](compare.h.md) two elements. | +| `advanced_cmp` | A function that compares two elements and supports custom data. If specified, this has precedence over the `simple_cmp` function. | +| `cmp_data` | A pointer to the custom data that shall be passed to the `advanced_cmp` function. | +| `simple_destructor` | An optional simple [destructor function](allocator.h.md#destructor-functions). | +| `advanced_destructor` | An optional advanced destructor function. | +| `destructor_data` | A pointer to the custom data that shall be passed to the advanced destructor. | +| `store_pointer` | A `bool` indicating whether this collection stores pointers instead of the element's data. | +| `sorted` | A `bool` indicating whether the elements are currently guaranteed sorted with respect to the compare function. | The attributes can be accessed directly via the `collection` member of your struct, or with the following convenience macros. @@ -44,15 +46,52 @@ In each case the argument `c` is a pointer to your collection. The macro will then access the base data with `c->collection`. -On the other hand, the following macros can be used to set the properties of a collection: +## Comparator Functions + +For working with comparators, the following macros are defined: ```C -cxSetCompareFunc(c, func) -cxSetDestructor(c, destr) -cxSetAdvancedDestructor(c, destr, data) +cxSetCompareFunc(c, func) +cxSetAdvancedCompareFunc(c, func, data) + +// use in your collection's implementation +cx_invoke_compare_func(c, left, right) + +// the following two can be used to optimize loops +cx_invoke_simple_compare_func(c, left, right) +cx_invoke_advanced_compare_func(c, left, right) + +// convenience macro for addressing and dereference elements in pointer collections +cx_ref(c, elem) +cx_deref(c, elem) ``` -More details on the destructor functions follow in the next section. +If an advanced compare function is specified, `cx_invoke_compare_func()` will only invoke the advanced comparator. +Otherwise, the simple comparator is invoked. +If neither comparator is specified, invoking a comparator leads to undefined behavior. + +In contrast to the destructors (below), comparators must always be invoked with a pointer to the element's data. +That means, if the collection is storing pointers, you must dereference the pointers to those pointers first, before invoking the comparator. +The reason for this is that the comparator cannot know if an argument points to an element of the collection or to external data the elements shall be compared with. + +A typical use case would be this: + +```C +void *arg = // ... passed as argument, e.g. in cxListContains() +void *elem = // ... get a pointer to the element +void *data; + +// manually ... +if (cxCollectionStoresPointers(this_collection)) { + data = *(void**)elem; +} else { + data = elem; +} + +// ... or with the convenience macro +data = cx_deref(this_collection, elem); +int result = cx_invoke_compare_func(this_collection, data, arg); +``` ## Destructor Functions @@ -65,7 +104,7 @@ // use in your collection's implementation cx_invoke_destructor(c, elem) -// the following two should not be used +// the following two can be used to optimize loops cx_invoke_simple_destructor(c, elem) cx_invoke_advanced_destructor(c, elem) ```