| 19 |
19 |
| 20 ## Base Attributes of a Collection |
20 ## Base Attributes of a Collection |
| 21 |
21 |
| 22 The following attributes are declared by the `CX_COLLECTION_BASE` macro: |
22 The following attributes are declared by the `CX_COLLECTION_BASE` macro: |
| 23 |
23 |
| 24 | Attribute | Description | |
24 | Attribute | Description | |
| 25 |-----------------------|----------------------------------------------------------------------------------------------------------------| |
25 |-----------------------|-----------------------------------------------------------------------------------------------------------------------------------| |
| 26 | `allocator` | The [allocator](allocator.h.md) that shall be used for the collection data. | |
26 | `allocator` | The [allocator](allocator.h.md) that shall be used for the collection data. | |
| 27 | `cmpfunc` | A function to [compare](compare.h.md) two elements. | |
27 | `elem_size` | The size of one element in bytes. | |
| 28 | `elem_size` | The size of one element in bytes. | |
28 | `size` | The size, meaning the number of elements, currently stored. | |
| 29 | `size` | The size, meaning the number of elements, currently stored. | |
29 | `simple_cmp` | A function to [compare](compare.h.md) two elements. | |
| 30 | `simple_destructor` | An optional simple [destructor function](allocator.h.md#destructor-functions). | |
30 | `advanced_cmp` | A function that compares two elements and supports custom data. If specified, this has precedence over the `simple_cmp` function. | |
| 31 | `advanced_destructor` | An optional advanced destructor function. | |
31 | `cmp_data` | A pointer to the custom data that shall be passed to the `advanced_cmp` function. | |
| 32 | `destructor_data` | A pointer to the custom data that shall be passed to the advanced destructor. | |
32 | `simple_destructor` | An optional simple [destructor function](allocator.h.md#destructor-functions). | |
| 33 | `store_pointer` | A `bool` indicating whether this collection stores pointers instead of the element's data. | |
33 | `advanced_destructor` | An optional advanced destructor function. | |
| 34 | `sorted` | A `bool` indicating whether the elements are currently guaranteed sorted with respect to the compare function. | |
34 | `destructor_data` | A pointer to the custom data that shall be passed to the advanced destructor. | |
| |
35 | `store_pointer` | A `bool` indicating whether this collection stores pointers instead of the element's data. | |
| |
36 | `sorted` | A `bool` indicating whether the elements are currently guaranteed sorted with respect to the compare function. | |
| 35 |
37 |
| 36 The attributes can be accessed directly via the `collection` member of your struct, or with the following convenience macros. |
38 The attributes can be accessed directly via the `collection` member of your struct, or with the following convenience macros. |
| 37 |
39 |
| 38 ```C |
40 ```C |
| 39 cxCollectionSize(c) |
41 cxCollectionSize(c) |
| 42 cxCollectionSorted(c) |
44 cxCollectionSorted(c) |
| 43 ``` |
45 ``` |
| 44 |
46 |
| 45 In each case the argument `c` is a pointer to your collection. The macro will then access the base data with `c->collection`. |
47 In each case the argument `c` is a pointer to your collection. The macro will then access the base data with `c->collection`. |
| 46 |
48 |
| 47 On the other hand, the following macros can be used to set the properties of a collection: |
49 ## Comparator Functions |
| |
50 |
| |
51 For working with comparators, the following macros are defined: |
| 48 |
52 |
| 49 ```C |
53 ```C |
| 50 cxSetCompareFunc(c, func) |
54 cxSetCompareFunc(c, func) |
| 51 cxSetDestructor(c, destr) |
55 cxSetAdvancedCompareFunc(c, func, data) |
| 52 cxSetAdvancedDestructor(c, destr, data) |
56 |
| |
57 // use in your collection's implementation |
| |
58 cx_invoke_compare_func(c, left, right) |
| |
59 |
| |
60 // the following two can be used to optimize loops |
| |
61 cx_invoke_simple_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) |
| 53 ``` |
67 ``` |
| 54 |
68 |
| 55 More details on the destructor functions follow in the next section. |
69 If an advanced compare function is specified, `cx_invoke_compare_func()` will only invoke the advanced comparator. |
| |
70 Otherwise, the simple comparator is invoked. |
| |
71 If neither comparator is specified, invoking a comparator leads to undefined behavior. |
| |
72 |
| |
73 In contrast to the destructors (below), comparators must always be invoked with a pointer to the element's data. |
| |
74 That means, if the collection is storing pointers, you must dereference the pointers to those pointers first, before invoking the comparator. |
| |
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. |
| |
76 |
| |
77 A typical use case would be this: |
| |
78 |
| |
79 ```C |
| |
80 void *arg = // ... passed as argument, e.g. in cxListContains() |
| |
81 void *elem = // ... get a pointer to the element |
| |
82 void *data; |
| |
83 |
| |
84 // manually ... |
| |
85 if (cxCollectionStoresPointers(this_collection)) { |
| |
86 data = *(void**)elem; |
| |
87 } else { |
| |
88 data = elem; |
| |
89 } |
| |
90 |
| |
91 // ... or with the convenience macro |
| |
92 data = cx_deref(this_collection, elem); |
| |
93 int result = cx_invoke_compare_func(this_collection, data, arg); |
| |
94 ``` |
| 56 |
95 |
| 57 ## Destructor Functions |
96 ## Destructor Functions |
| 58 |
97 |
| 59 For working with destructors, the following macros are defined: |
98 For working with destructors, the following macros are defined: |
| 60 |
99 |
| 63 cxSetAdvancedDestructor(c, destr, data) |
102 cxSetAdvancedDestructor(c, destr, data) |
| 64 |
103 |
| 65 // use in your collection's implementation |
104 // use in your collection's implementation |
| 66 cx_invoke_destructor(c, elem) |
105 cx_invoke_destructor(c, elem) |
| 67 |
106 |
| 68 // the following two should not be used |
107 // the following two can be used to optimize loops |
| 69 cx_invoke_simple_destructor(c, elem) |
108 cx_invoke_simple_destructor(c, elem) |
| 70 cx_invoke_advanced_destructor(c, elem) |
109 cx_invoke_advanced_destructor(c, elem) |
| 71 ``` |
110 ``` |
| 72 |
111 |
| 73 With `cxSetDestructor()` you can assign a simple [destructor function](allocator.h.md#destructor-functions) |
112 With `cxSetDestructor()` you can assign a simple [destructor function](allocator.h.md#destructor-functions) |