| 58 cx_invoke_compare_func(c, left, right) |
58 cx_invoke_compare_func(c, left, right) |
| 59 |
59 |
| 60 // the following two can be used to optimize loops |
60 // the following two can be used to optimize loops |
| 61 cx_invoke_simple_compare_func(c, left, right) |
61 cx_invoke_simple_compare_func(c, left, right) |
| 62 cx_invoke_advanced_compare_func(c, left, right) |
62 cx_invoke_advanced_compare_func(c, left, right) |
| 63 |
|
| 64 // convenience macro for addressing and dereference elements in pointer collections |
|
| 65 cx_ref(c, elem) |
|
| 66 cx_deref(c, elem) |
|
| 67 ``` |
63 ``` |
| 68 |
64 |
| 69 If an advanced compare function is specified, `cx_invoke_compare_func()` will only invoke the advanced comparator. |
65 If an advanced compare function is specified, `cx_invoke_compare_func()` will only invoke the advanced comparator. |
| 70 Otherwise, the simple comparator is invoked. |
66 Otherwise, the simple comparator is invoked. |
| 71 If neither comparator is specified, invoking a comparator leads to undefined behavior. |
67 If neither comparator is specified, invoking a comparator leads to undefined behavior. |
| 75 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. |
71 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. |
| 76 |
72 |
| 77 A typical use case would be this: |
73 A typical use case would be this: |
| 78 |
74 |
| 79 ```C |
75 ```C |
| 80 void *arg = // ... passed as argument, e.g. in cxListContains() |
76 void *arg = // ... passed as argument |
| 81 void *elem = // ... get a pointer to the element |
77 void *elem = // ... get a pointer to the element |
| 82 void *data; |
78 void *data; |
| 83 |
79 |
| 84 // manually ... |
80 // manually ... |
| 85 if (cxCollectionStoresPointers(this_collection)) { |
81 if (cxCollectionStoresPointers(this_collection)) { |
| 86 data = *(void**)elem; |
82 data = *(void**)elem; |
| 87 } else { |
83 } else { |
| 88 data = elem; |
84 data = elem; |
| 89 } |
85 } |
| 90 |
86 |
| 91 // ... or with the convenience macro |
87 // ... or with a convenience macro |
| 92 data = cx_deref(this_collection, elem); |
88 data = cx_deref(this_collection, elem); |
| 93 int result = cx_invoke_compare_func(this_collection, data, arg); |
89 int result = cx_invoke_compare_func(this_collection, data, arg); |
| 94 ``` |
90 ``` |
| |
91 |
| |
92 > When you are implementing a custom `CxList`, the above handling of pointers vs. elements is implemented |
| |
93 > by `cx_list_compare_wrapper`, a `cx_compare_func2` which takes the `list` as third argument. |
| |
94 > It will do the dereferencing for you. |
| |
95 > |
| |
96 > It is important that both arguments, left and right, for the compare function are either both pointers to pointers |
| |
97 > or both pointers to elements, but never mixed. |
| 95 |
98 |
| 96 ## Destructor Functions |
99 ## Destructor Functions |
| 97 |
100 |
| 98 For working with destructors, the following macros are defined: |
101 For working with destructors, the following macros are defined: |
| 99 |
102 |
| 119 |
122 |
| 120 > Destructor functions are always invoked with a pointer to the element in your collection. |
123 > Destructor functions are always invoked with a pointer to the element in your collection. |
| 121 > If your collection is storing pointers (i.e. `cxCollectionStoresPointers()` returns `true`) |
124 > If your collection is storing pointers (i.e. `cxCollectionStoresPointers()` returns `true`) |
| 122 > the `cx_invoke_destructor()` will make sure that the pointer to the element is dereferenced first, |
125 > the `cx_invoke_destructor()` will make sure that the pointer to the element is dereferenced first, |
| 123 > so that the destructor functions are _always_ invoked with a pointer to the actual element. |
126 > so that the destructor functions are _always_ invoked with a pointer to the actual element. |
| |
127 > |
| |
128 > This is different to how [comparator functions](#comparator-functions) work. |
| 124 {style="note"} |
129 {style="note"} |
| 125 |
130 |
| 126 <seealso> |
131 <seealso> |
| 127 <category ref="apidoc"> |
132 <category ref="apidoc"> |
| 128 <a href="https://ucx.sourceforge.io/api/collection_8h.html">collection.h</a> |
133 <a href="https://ucx.sourceforge.io/api/collection_8h.html">collection.h</a> |