docs/Writerside/topics/list.h.md

changeset 1239
b4b1f15d1866
parent 1238
26299ce9c955
equal deleted inserted replaced
1238:26299ce9c955 1239:b4b1f15d1866
8 8
9 UCX already comes with two common list implementations ([linked list](linked_list.h.md) and [array list](array_list.h.md)) 9 UCX already comes with two common list implementations ([linked list](linked_list.h.md) and [array list](array_list.h.md))
10 that should cover most use cases. 10 that should cover most use cases.
11 But if you feel the need to implement an own list, you will find instructions [below](#implement-own-list-structures). 11 But if you feel the need to implement an own list, you will find instructions [below](#implement-own-list-structures).
12 12
13 ```C
14 #include <cx/linked_list.h>
15
16 CxList *cxLinkedListCreate(const CxAllocator *allocator,
17 cx_compare_func comparator, size_t elem_size);
18
19 CxList *cxLinkedListCreateSimple(size_t elem_size);
20
21 #include <cx/array_list.h>
22
23 CxList *cxArrayListCreate(const CxAllocator *allocator,
24 cx_compare_func comparator, size_t elem_size,
25 size_t initial_capacity);
26
27 CxList *cxArrayListCreateSimple(size_t elem_size,
28 size_t initial_capacity);
29 ```
30
31 The function `cxLinkedListCreate()` creates a new linked list with the specified `allocator` which stores elements of size `elem_size`.
32 The elements are supposed to be compared with the specified `comparator` (cf. [](#access-and-find)).
33 The function `cxLinkedListCreateSimple()` will use the stdlib default allocator and does not specify a compare function.
34
35 Array lists can be created with `cxArrayListCreate()` where the additional argument `initial_capacity` specifies for how many elements the underlying array shall be initially allocated.
36
37 If `CX_STORE_POINTERS` is used as `elem_size`, the actual element size will be `sizeof(void*)` and the list will behave slightly differently when accessing elements.
38 Lists that are storing pointers will always return the stored pointer directly, instead of returning a pointer into the list's memory, thus saving you from unnecessary dereferencing.
39 Conversely, when adding elements to the list, the pointers you specify (e.g. in `cxListAdd()` or `cxListInsert()`) are directly added to the list, instead of copying the contents pointed to by the argument.
40
41 > When you create a list which is storing pointers and do not specify a compare function, `cx_cmp_ptr` will be used by default.
42
13 ## Example 43 ## Example
14 44
15 <warning> 45 <warning>
16 TODO: add example how to work with lists 46 TODO: add example how to work with lists
17 </warning> 47 </warning>
18 48
19 > If you want to lazy-initialize lists, you can use the global `cxEmptyList` symbol as a placeholder instead of using a `NULL`-pointer. 49 > If you want to lazy-initialize lists, you can use the global `cxEmptyList` symbol as a placeholder instead of using a `NULL`-pointer.
20 > While you *must not* insert items into that list, you can safely access this list or create iterators. 50 > While you *must not* insert elements into that list, you can safely access this list or create iterators.
21 > This allows you to write clean code without checking for `NULL`-pointer everywhere. 51 > This allows you to write clean code without checking for `NULL`-pointer everywhere.
22 > You still need to make sure that the placeholder is replaced with an actual list before inserting items. 52 > You still need to make sure that the placeholder is replaced with an actual list before inserting elements.
23 53
24 ## Insert 54 ## Insert
25 55
26 ```C 56 ```C
57 #include <cx/list.h>
58
27 int cxListAdd(CxList *list, const void *elem); 59 int cxListAdd(CxList *list, const void *elem);
28 60
61 int cxListInsert(CxList *list, size_t index, const void *elem);
62
63 int cxListInsertSorted(CxList *list, const void *elem);
64
29 size_t cxListAddArray(CxList *list, const void *array, size_t n); 65 size_t cxListAddArray(CxList *list, const void *array, size_t n);
30
31 int cxListInsert(CxList *list, size_t index, const void *elem);
32
33 int cxListInsertSorted(CxList *list, const void *elem);
34 66
35 size_t cxListInsertArray(CxList *list, size_t index, 67 size_t cxListInsertArray(CxList *list, size_t index,
36 const void *array, size_t n); 68 const void *array, size_t n);
37 69
38 size_t cxListInsertSortedArray(CxList *list, 70 size_t cxListInsertSortedArray(CxList *list,
41 int cxListInsertAfter(CxIterator *iter, const void *elem); 73 int cxListInsertAfter(CxIterator *iter, const void *elem);
42 74
43 int cxListInsertBefore(CxIterator *iter, const void *elem); 75 int cxListInsertBefore(CxIterator *iter, const void *elem);
44 ``` 76 ```
45 77
46 <warning> 78 The function `cxListAdd()` appends the element `elem` to the list and returns zero on success or non-zero when allocating the memory for the element fails.
47 TODO: add documentation 79 Similarly, `cxListInsert()` adds the element at the specified `index`,
48 </warning> 80 and `cxListInsertSorted()` adds the element at the correct position so that the list remains sorted according to the list's compare function.
81
82 When you are currently iterating through a list, you can insert items before or after the current position of the iterator
83 with `cxListInsertBefore()` or `cxListInsertAfter()`, respectively.
84 This _should_ be done with [mutating iterators](iterator.h.md#mutating-iterators) only, but is also defined for normal iterators.
85
86 If the list is storing pointers (cf. `cxCollectionStoresPointers()`), the pointer `elem` is directly added to the list.
87 Otherwise, the contents at the location pointed to by `elem` are copied to the list's memory with the element size specified during creation of the list.
88
89 On the other hand the `array` argument for `cxListAddArray()`, `cxListInsertArray()`, and `cxListInsertSortedArray()`
90 must always point to an array of elements to be added (i.e. either an array of pointers, or an array of actual elements).
91
92 A special requirement for `cxListInsertSortedArray()` is, that the `array` must already be sorted.
93
94 > Implementations are required to optimize the insertion of a sorted array into a sorted list in linear time,
95 > while inserting each element separately via `cxListInsertSorted()` may take quadratic time.
96
97 > The functions `cxListInsertSorted()` and `cxListInsertSortedArray()` do neither check if the list is already sorted, nor do they actively sort the list.
98 > {style="note"}
49 99
50 ## Access and Find 100 ## Access and Find
51 101
52 ```C 102 <link-summary>Functions for searching and accessing elements.</link-summary>
103
104 ```C
105 #include <cx/list.h>
106
107 void *cxListAt(const CxList *list, size_t index);
108
109 size_t cxListFind(const CxList *list, const void *elem);
110
111 size_t cxListFindRemove(CxList *list, const void *elem);
112
113 bool cxListIndexValid(const CxList *list, size_t index);
114
53 size_t cxListSize(const CxList *list); 115 size_t cxListSize(const CxList *list);
54 116 ```
55 void *cxListAt(const CxList *list, size_t index); 117
56 118 The function `cxListAt()` accesses the element at the specified `index`.
57 size_t cxListFind(const CxList *list, const void *elem); 119 If the list is storing pointers (i.e. `cxCollectionStoresPointers()` returns `true`), the pointer at the specified index is directly returned.
58 120 Otherwise, a pointer to element at the specified index is returned.
59 size_t cxListFindRemove(CxList *list, const void *elem); 121 If the index is out-of-bounds, the function returns `NULL`.
60 122
61 bool cxListIndexValid(const CxList *list, size_t index); 123 On the other hand, `cxListFind()` searches for the element pointed to by `elem` by comparing each element in the list with the list`s compare function,
62 ``` 124 and returns the first index when the element was found.
63 125 Otherwise, the function returns the list size.
64 <warning> 126
65 TODO: add documentation 127 The function `cxListFindRemove()` behaves like `cxListFind()`, except that it also removes the first occurrence of the element from the list.
66 </warning> 128 This will _also_ call destructor functions, if specified, so take special care when you continue to use `elem`, or when the list is storing pointers and the element appears more than once in the list.
129
130 With `cxListIndexValid()` you can check the index returned by `cxListFind()` or `cxListFindRemove()`,
131 which is more convenient than comparing the return value if the return value of `cxListSize()`.
67 132
68 ## Remove 133 ## Remove
69 134
70 ```C 135 ```C
136 #include <cx/list.h>
137
71 int cxListRemove(CxList *list, size_t index); 138 int cxListRemove(CxList *list, size_t index);
72 139
140 size_t cxListRemoveArray(CxList *list, size_t index, size_t num);
141
73 int cxListRemoveAndGet(CxList *list, size_t index, void *targetbuf); 142 int cxListRemoveAndGet(CxList *list, size_t index, void *targetbuf);
74
75 size_t cxListRemoveArray(CxList *list, size_t index, size_t num);
76 143
77 size_t cxListRemoveArrayAndGet(CxList *list, size_t index, size_t num, 144 size_t cxListRemoveArrayAndGet(CxList *list, size_t index, size_t num,
78 void *targetbuf); 145 void *targetbuf);
146
147 size_t cxListFindRemove(CxList *list, const void *elem);
79 148
80 void cxListClear(CxList *list); 149 void cxListClear(CxList *list);
81 ``` 150 ```
82 151
83 <warning> 152 The function `cxListRemove()` removes the element at the specified index and returns zero,
84 TODO: add documentation 153 or returns non-zero if the index is out-of-bounds.
85 </warning> 154 The function `cxListRemoveArray()` removes `num` elements starting at `index` and returns the number of elements that have been removed.
155 For each removed element, the [destructor functions](collection.h.md#destructor-functions) are called.
156
157 On the other hand, `cxListRemoveAndGet()` and `cxListRemoveArrayAndGet()` do not invoke the destructor functions
158 and instead copy the elements into the `targetbuf`, which must be large enough to hold the removed elements.
159
160 The function `cxListFindRemove()` finds the first element within the list that is equivalent to the element pointed to by `elem` and removes it from the list.
161 This will _also_ call destructor functions, if specified, so take special care when you continue to use `elem`.
162
163 The function `cxListClear()` simply removes all elements from the list, invoking the destructor functions.
164 It behaves equivalently, but is usually more efficient than calling `cxListRemove()` for every index.
86 165
87 ## Iterators 166 ## Iterators
88 167
89 ```C 168 ```C
169 #include <cx/list.h>
170
90 CxIterator cxListIterator(const CxList *list); 171 CxIterator cxListIterator(const CxList *list);
91 172
173 CxIterator cxListBackwardsIterator(const CxList *list);
174
175 CxIterator cxListIteratorAt(const CxList *list, size_t index);
176
177 CxIterator cxListBackwardsIteratorAt(const CxList *list, size_t index);
178
92 CxIterator cxListMutIterator(CxList *list); 179 CxIterator cxListMutIterator(CxList *list);
93 180
94 CxIterator cxListBackwardsIterator(const CxList *list);
95
96 CxIterator cxListMutBackwardsIterator(CxList *list); 181 CxIterator cxListMutBackwardsIterator(CxList *list);
97 182
98 CxIterator cxListIteratorAt(const CxList *list, size_t index);
99
100 CxIterator cxListBackwardsIteratorAt(const CxList *list, size_t index);
101
102 CxIterator cxListMutIteratorAt(CxList *list, size_t index); 183 CxIterator cxListMutIteratorAt(CxList *list, size_t index);
103 184
104 CxIterator cxListMutBackwardsIteratorAt(CxList *list, size_t index); 185 CxIterator cxListMutBackwardsIteratorAt(CxList *list, size_t index);
105 ``` 186 ```
106 187
107 <warning> 188 The functions `cxListIterator()` and `cxListBackwardsIterator()` create iterators
108 TODO: add documentation 189 that start and the first or the last element in the list and iterate through the entire list.
109 </warning> 190
191 The functions `cxListIteratorAt()` and `cxListBackwardsIteratorAt()` start with the element at the specified index
192 and iterate until the end, or the beginning of the list, respectively.
193
194 The functions with `Mut` in are equivalently, except that they create a [mutating iterator](iterator.h.md#mutating-iterators).
195 Removing elements via a mutating iterator will cause an invocation of the [destructor functions](collection.h.md#destructor-functions) for the removed element.
196
197 If is safe to specify an out-of-bounds index in which case an iterator is returned for which `cxIteratorValid()` returns `false`, immediately.
110 198
111 ## Reorder 199 ## Reorder
112 200
113 ```C 201 ```C
202 #include <cx/list.h>
203
114 int cxListSwap(CxList *list, size_t i, size_t j); 204 int cxListSwap(CxList *list, size_t i, size_t j);
115 205
206 void cxListReverse(CxList *list);
207
116 void cxListSort(CxList *list); 208 void cxListSort(CxList *list);
117 209 ```
118 void cxListReverse(CxList *list); 210
119 ``` 211 The function `cxListSwap()` swaps two elements specified by the indices `i` and `j`.
120 212 The return value is non-zero if one of the indices is out-of-bounds.
121 <warning> 213
122 TODO: add documentation 214 The function `cxListReverse()` reorders all elements, so that they appear in exactly the opposite order after invoking this function.
123 </warning> 215
216 The function `cxListSort()` sorts all elements with respect to the list's compare function,
217 unless the list is already sorted (cf. `cxCollectionSorted()`), in which case the function immediately returns.
218
219 Default UCX implementations of the list interface make use of [small buffer optimizations](install.md#small-buffer-optimizations) when swapping elements.
220
221 > An invocation of `cxListSort` sets the `sorted` flag of the [collection](collection.h.md).
222 > Implementations usually make use of this flag to optimize search operations, if possible.
223 > For example the [array list](array_list.h.md) implementation will use binary search
224 > for `cxListFind()` and similar operations, when the list is sorted.
124 225
125 ## Compare 226 ## Compare
126 227
127 ```C 228 ```C
229 #include <cx/list.h>
230
128 int cxListCompare(const CxList *list, const CxList *other); 231 int cxListCompare(const CxList *list, const CxList *other);
129 ``` 232 ```
130 233
131 Arbitrary lists can be compared item-wise with `cxListCompare()`, as long as the compare functions of both lists are equivalent. 234 Arbitrary lists can be compared element-wise with `cxListCompare()`, as long as the compare functions of both lists are equivalent.
132 235
133 That means, you can compare an UCX [array list](array_list.h.md) with a [linked list](linked_list.h.md), 236 That means, you can compare an UCX [array list](array_list.h.md) with a [linked list](linked_list.h.md),
134 and you could even compare lists that are storing pointers with lists that are not storing pointers. 237 and you could even compare lists that are storing pointers with lists that are not storing pointers.
135 238
136 However, the optimized list-internal compare implementation is only used, when both the compare functions and the list classes are identical. 239 However, the optimized list-internal compare implementation is only used, when both the compare functions and the list classes are identical.
137 Otherwise, `cxListCompare()` will behave as if you were iterating through both lists and manually comparing the items. 240 Otherwise, `cxListCompare()` will behave as if you were iterating through both lists and manually comparing the elements.
138 241
139 The return value of `cxListCompare()` is zero, if the lists are item-wise equivalent. 242 The return value of `cxListCompare()` is zero, if the lists are element-wise equivalent.
140 If they are not, the non-zero return value equals the return value of the used compare function for the first pair of elements that are not equal. 243 If they are not, the non-zero return value equals the return value of the used compare function for the first pair of elements that are not equal.
141 244
142 ## Dispose 245 ## Dispose
143 246
144 ```C 247 ```C
248 #include <cx/list.h>
249
145 void cxListFree(CxList *list); 250 void cxListFree(CxList *list);
146 ``` 251 ```
147 252
148 No matter with which function a `CxList` has been created, you can _always_ deallocate the entire memory with a call to `cxListFree()`. 253 No matter with which function a `CxList` has been created, you can _always_ deallocate the entire memory with a call to `cxListFree()`.
149 254
150 The effect is equivalent to invoking `cxListClear()` plus deallocating the memory for the list structure. 255 The effect is equivalent to invoking `cxListClear()` plus deallocating the memory for the list structure.
151 That means, for each item in the list, the destructor functions defined by `cxDefineDestructor()` or `cxDefineAdvancedDestructor()` are called, 256 That means, for each element in the list, the [destructor functions](collection.h.md#destructor-functions) are called before deallocating the list.
152 before deallocating the list.
153 257
154 When the list has been storing pointers, make sure that either another reference to the same memory exist in your program, 258 When the list has been storing pointers, make sure that either another reference to the same memory exist in your program,
155 or any of the destructor functions deallocates the memory. 259 or any of the destructor functions deallocates the memory.
156 Otherwise, there is a risk of a memory leak. 260 Otherwise, there is a risk of a memory leak.
157 261

mercurial