docs/Writerside/topics/array_list.h.md

changeset 1248
fc5e63b04281
parent 1246
5f2c9750204c
equal deleted inserted replaced
1247:e30d38e06559 1248:fc5e63b04281
103 103
104 CxArrayReallocator cx_array_reallocator( 104 CxArrayReallocator cx_array_reallocator(
105 const struct cx_allocator_s *allocator, 105 const struct cx_allocator_s *allocator,
106 const void *stackmem 106 const void *stackmem
107 ); 107 );
108 ``` 108
109 109 extern CxArrayReallocator* cx_array_default_reallocator;
110 <warning> 110 ```
111 TODO: document 111
112 </warning> 112 The main purpose of the functions defined in the array list header,
113 113 is to make it easier to write to an array without caring too much about a possibly needed reallocation.
114 ## Add Elements 114
115 115 This is realized by passing a reallocator to the various functions which specifies how an array shall be reallocated when needed.
116 ```C 116
117 #include <cx/array_list.h> 117 The default `cx_array_default_reallocator` simply defers to the standard library `realloc()`.
118 118
119 int cx_array_add(void **target, void *size, void *capacity, 119 A reallocator created with the `cx_array_reallocator()` function uses a more sophisticated approach.
120 size_t elem_size, const void *elem, 120 On the one hand, it can use an arbitrary UCX [allocator](allocator.h.md) for the reallocation,
121 CxArrayReallocator *reallocator); 121 and on the other hand, it can optionally keep track of a stack memory pointer.
122 122 If you pass a non-`NULL` pointer to `stackmem`, the reallocator will _always_ allocate _new_ memory for the array,
123 #define cx_array_simple_add(ARRAY, elem) 123 if the current location equals the `stackmem` address.
124 124
125 #define cx_array_simple_add_a(reallocator, ARRAY, elem) 125 This allows you to allocate an array on the stack and instruct UCX to automatically move it to heap memory when the capacity is exceeded.
126 ``` 126 Combined with a UCX [memory pool](mempool.h.md) this can be a powerful tool for local arrays
127 127 which are expected to stay within the bounds of the stack memory most of the time, but are also allowed to sometimes grow their capacity when needed.
128 <warning>
129 TODO: document
130 </warning>
131 128
132 ## Reserve 129 ## Reserve
133 130
134 ```C 131 ```C
135 #include <cx/array_list.h> 132 #include <cx/array_list.h>
136 133
137 int cx_array_reserve( 134 int cx_array_reserve(
138 void **array, void *size, void *capacity, unsigned width, 135 void **array, void *size, void *capacity, unsigned width,
139 size_t elem_size, size_t elem_count, 136 size_t elem_size, size_t count,
140 CxArrayReallocator *reallocator); 137 CxArrayReallocator *reallocator);
141 138
142 #define cx_array_simple_reserve(ARRAY, count) 139 #define cx_array_simple_reserve(ARRAY, count)
143 #define cx_array_simple_reserve_a(reallocator, ARRAY, count) 140 #define cx_array_simple_reserve_a(reallocator, ARRAY, count)
144 ``` 141 ```
145 142
146 <warning> 143 The function `cx_array_reserve()` guarantees that at least `count` _additional_ elements
147 TODO: document 144 can be stored in the array pointed to by `array`.
148 </warning> 145
146 The `array` argument is a pointer to the location of the target array pointer.
147 The reason for this additional indirection is that this function writes
148 a new pointer back to that variable, if the array needed to be reallocated.
149
150 If reallocation fails, this function returns non-zero leaving the array as it was.
151 Otherwise, the function returns zero.
152
153 If `*size + elem_count` does not exceed the current `*capacity`, this function does nothing and simply returns zero.
154 Otherwise, the specified `reallocator` is used to reserve the necessary space.
155 If reallocation was necessary but failed, this function returns non-zero.
156
157 The actual data type of `size` and `capacity` can be a pointer to an arbitrary integer whose byte-width is determined by the `width` argument.
158 On 32-bit platforms the widths 1, 2, and 4 are supported and on 64-bit platforms, additionally a width of 8 is supported.
159 Passing zero as argument makes the function assume the native width for size arguments `sizeof(size_t)`.
160
161 The convenience macros take the _name_ of an array variable and invoke the function by deducing the other arguments
162 (including the width of the size and capacity).
163 The reallocator used by the `cx_array_simple_reserve()` macro is the `cx_array_default_reallocator`.
164
165 > While the actual integer type for `size` and `capacity` can be chosen freely, it must be _the same_ for both variables.
166 > For example it is not allowed, and it does not make any sense either, to use a 16-bit integer for the size, but a 32-bit integer for the capacity.
149 167
150 ## Copy 168 ## Copy
151 169
152 ```C 170 ```C
153 #include <cx/array_list.h> 171 #include <cx/array_list.h>
161 #define cx_array_simple_copy(ARRAY, index, src, count) 179 #define cx_array_simple_copy(ARRAY, index, src, count)
162 180
163 #define cx_array_simple_copy_a(reallocator, ARRAY, index, src, count) 181 #define cx_array_simple_copy_a(reallocator, ARRAY, index, src, count)
164 ``` 182 ```
165 183
166 <warning> 184 The function `cx_array_copy()` first [reserves](#reserve) enough memory to copy `elem_count` number of elements from the `src` array
167 TODO: outdated - rewrite 185 to the target array at the specified `index`, and then copies the data with one call to `memmove()`.
168 </warning>
169
170 The `target` argument is a pointer to the target array pointer.
171 The reason for this additional indirection is that this function writes
172 back the pointer to the possibly reallocated array.
173 The next two arguments are pointers to the `size` and `capacity` of the target array for which the width
174 (in bits) is specified in the `width` argument.
175
176 On a successful invocation, the function copies `elem_count` number of elements, each of size `elem_size` from
177 `src` to `*target` and uses the `reallocator` to extend the array when necessary.
178 Finally, the size, capacity, and the pointer to the array are all updated and the function returns zero.
179 186
180 A few things to note: 187 A few things to note:
181 * `*target` and `src` can point to the same memory region, effectively copying elements within the array with `memmove` 188 * `*target` and `src` can point to the same memory region, since the underlying copy operation is a `memmove()`
182 * `*target` does not need to point to the start of the array, but `size` and `capacity` always start counting from the 189 * `*target` does not need to point to the start of the array, but `size` and `capacity` always start counting from the
183 position, `*target` points to - in this scenario, the need for reallocation must be avoided for obvious reasons 190 position `*target` points to - in this scenario, the need for reallocation must be avoided for obvious reasons
184 * `index` does not need to be within size of the current array 191 * `index` does not need to be within size and not even within the capacity of the current array
185 * `index` does not even need to be within the capacity of the array 192 * if `index` equals `*size`, this function effectively appends the data to the target array
186 * `width` must be one of 8, 16, 32, 64 (only on 64-bit systems), or zero (in which case the native word width is used) 193 * the data in the target array is overwritten - if you want to insert data, you first need to copy the existing data to the end of the array and then copy the new data in a separate call
194
195 > If you are using `cx_array_reserve()` already in your program, there is no need to call `cx_array_copy()` or any of the convenience macros anymore.
196 > In other words: if you already guarantee, by any means, that no reallocation is necessary when writing to your array,
197 > it is strongly recommended to use standard library functions or direct index-based access instead of the UCX functions,
198 > which only purpose is to make it easier for you to guarantee that your array's capacity is large enough to hold new elements.
199
200 ## Add Elements
201
202 ```C
203 #include <cx/array_list.h>
204
205 #define cx_array_add(target, size, capacity, elem_size, elem,
206 reallocator);
207
208 #define cx_array_simple_add(ARRAY, elem)
209
210 #define cx_array_simple_add_a(reallocator, ARRAY, elem)
211 ```
212
213 The macros for adding an element are all convenience macros that invoke `cx_array_copy()`
214 interpreting the `elem` as an array of size one, copied to the past-by-one index of the target array.
187 215
188 ## Insertion Sort 216 ## Insertion Sort
189 217
190 ```C 218 ```C
191 int cx_array_insert_sorted( 219 int cx_array_insert_sorted(
198 src, elem_count, cmp_func) 226 src, elem_count, cmp_func)
199 227
200 #define cx_array_simple_insert_sorted_a(reallocator, ARRAY, 228 #define cx_array_simple_insert_sorted_a(reallocator, ARRAY,
201 src, elem_count, cmp_func) 229 src, elem_count, cmp_func)
202 230
203 int cx_array_add_sorted( 231 #define cx_array_add_sorted(target, size, capacity,
204 void **target, size_t *size, size_t *capacity, 232 elem_size, elem, cx_compare_func cmp_func, reallocator);
205 size_t elem_size, const void *elem,
206 cx_compare_func cmp_func,
207 CxArrayReallocator *reallocator);
208 233
209 #define cx_array_simple_add_sorted(ARRAY, 234 #define cx_array_simple_add_sorted(ARRAY,
210 elem, cmp_func) 235 elem, cmp_func)
211 236
212 #define cx_array_simple_add_sorted_a(reallocator, ARRAY, 237 #define cx_array_simple_add_sorted_a(reallocator, ARRAY,
213 elem, cmp_func) 238 elem, cmp_func)
214 ``` 239 ```
215 240
216 <warning> 241 The function `cx_array_insert_sorted()` inserts the `elem_count` number of already sorted elements from the `src` array
217 TODO: document 242 into the target array, comparing the elements with the given `cmp_func`.
218 </warning> 243
244 The arguments of this function are used similar to [`cx_array_copy()`](#copy) with two notable exceptions:
245 first, this function actually inserts the items, moving existing items when necessary, and second,
246 no particular index is required because this function determines the insertion points automatically using [binary search](#binary-search).
247
248 If either the target or the source array is not already sorted with respect to the given compare function, the behavior is undefined.
249
250 The convenience macros are all calling `cx_array_insert_sorted()` by deducing the missing arguments.
251 The `cx_array_add_sorted()` family of macros are interpreting the `elem` as a `src` array with an `elem_count` of one.
219 252
220 ## Binary Search 253 ## Binary Search
221 254
222 ```C 255 ```C
223 #include <cx/array_list.h> 256 #include <cx/array_list.h>
233 size_t cx_array_binary_search_sup( 266 size_t cx_array_binary_search_sup(
234 const void *arr, size_t size, size_t elem_size, 267 const void *arr, size_t size, size_t elem_size,
235 const void *elem, cx_compare_func cmp_func); 268 const void *elem, cx_compare_func cmp_func);
236 ``` 269 ```
237 270
238 <warning> 271 The function `cx_array_binary_search()` searches the array `arr` for the data pointed to by `elem` using the compare function `cmp_func`.
239 TODO: document 272
240 </warning> 273 If the element is found (i.e. `cmp_func` returns zero), the function returns the index of the element.
274 Otherwise, the function returns `size`.
275
276 The functions `cx_array_binary_search_inf()` and `cx_array_binary_search_sup()` are equivalent,
277 except that they return the index of the closest element, if the searched element is not found.
278 The former function returns the closest element that is less or equal (greatest lower bound / infimum),
279 and the latter function returns the closest element that is larger or equal (least upper bound / supremum)
280 than the searched element.
281
282 > Note, that all of the above functions are only well-defined on arrays which are sorted with respect to the given compare function.
283 >
284 > This can, for example, easily be achieved by calling the standard library's `qsort()` function.
285 >{style="note"}
286
287 > Despite the name, neither C nor POSIX standards require the standard library's `bsearch()` function to be implemented using binary search.
288 > But observations show that it usually is.
289 > This makes `cx_array_binary_search()` likely to be equivalent to `bsearch()`, except that it returns an index rather than a pointer.
241 290
242 ## Iterators 291 ## Iterators
243 292
244 ```C 293 ```C
245 #include <cx/iterator.h> 294 #include <cx/iterator.h>
269 size_t idx1, 318 size_t idx1,
270 size_t idx2 319 size_t idx2
271 ); 320 );
272 ``` 321 ```
273 322
274 <warning> 323 The function `cx_array_swap()` exchanges two items with a three-way swap.
275 TODO: document 324
276 </warning> 325 No memory is allocated if the element size `elem_size` is not larger than `CX_ARRAY_SWAP_SBO_SIZE` (cf. [](install.md#small-buffer-optimizations)).
326
327 You have to make sure that both indices are within bounds of the array `arr`.
277 328
278 <seealso> 329 <seealso>
279 <category ref="apidoc"> 330 <category ref="apidoc">
280 <a href="https://ucx.sourceforge.io/api/array__list_8h.html">array_list.h</a> 331 <a href="https://ucx.sourceforge.io/api/array__list_8h.html">array_list.h</a>
281 </category> 332 </category>

mercurial