| 74 * Destructor function. |
74 * Destructor function. |
| 75 * |
75 * |
| 76 * Implementations SHALL invoke the content destructor functions if provided |
76 * Implementations SHALL invoke the content destructor functions if provided |
| 77 * and SHALL deallocate the entire list memory. |
77 * and SHALL deallocate the entire list memory. |
| 78 */ |
78 */ |
| 79 cx_attr_nonnull |
|
| 80 void (*deallocate)(struct cx_list_s *list); |
79 void (*deallocate)(struct cx_list_s *list); |
| 81 |
80 |
| 82 /** |
81 /** |
| 83 * Member function for inserting a single element. |
82 * Member function for inserting a single element. |
| 84 * Implementors SHOULD see to performant implementations for corner cases. |
83 */ |
| 85 */ |
|
| 86 cx_attr_nonnull |
|
| 87 int (*insert_element)( |
84 int (*insert_element)( |
| 88 struct cx_list_s *list, |
85 struct cx_list_s *list, |
| 89 size_t index, |
86 size_t index, |
| 90 const void *data |
87 const void *data |
| 91 ); |
88 ); |
| 92 |
89 |
| 93 /** |
90 /** |
| 94 * Member function for inserting multiple elements. |
91 * Member function for inserting multiple elements. |
| 95 * Implementors SHOULD see to performant implementations for corner cases. |
92 * |
| 96 * @see cx_list_default_insert_array() |
93 * @see cx_list_default_insert_array() |
| 97 */ |
94 */ |
| 98 cx_attr_nonnull |
|
| 99 size_t (*insert_array)( |
95 size_t (*insert_array)( |
| 100 struct cx_list_s *list, |
96 struct cx_list_s *list, |
| 101 size_t index, |
97 size_t index, |
| 102 const void *data, |
98 const void *data, |
| 103 size_t n |
99 size_t n |
| 106 /** |
102 /** |
| 107 * Member function for inserting sorted elements into a sorted list. |
103 * Member function for inserting sorted elements into a sorted list. |
| 108 * |
104 * |
| 109 * @see cx_list_default_insert_sorted() |
105 * @see cx_list_default_insert_sorted() |
| 110 */ |
106 */ |
| 111 cx_attr_nonnull |
|
| 112 size_t (*insert_sorted)( |
107 size_t (*insert_sorted)( |
| 113 struct cx_list_s *list, |
108 struct cx_list_s *list, |
| 114 const void *sorted_data, |
109 const void *sorted_data, |
| 115 size_t n |
110 size_t n |
| 116 ); |
111 ); |
| 117 |
112 |
| 118 /** |
113 /** |
| 119 * Member function for inserting an element relative to an iterator position. |
114 * Member function for inserting an element relative to an iterator position. |
| 120 */ |
115 */ |
| 121 cx_attr_nonnull |
|
| 122 int (*insert_iter)( |
116 int (*insert_iter)( |
| 123 struct cx_iterator_s *iter, |
117 struct cx_iterator_s *iter, |
| 124 const void *elem, |
118 const void *elem, |
| 125 int prepend |
119 int prepend |
| 126 ); |
120 ); |
| 127 |
121 |
| 128 /** |
122 /** |
| 129 * Member function for removing elements. |
123 * Member function for removing elements. |
| 130 * |
124 * |
| 131 * Implementations SHALL check if \p targetbuf is set and copy the elements |
125 * Implementations SHALL check if @p targetbuf is set and copy the elements |
| 132 * to the buffer without invoking any destructor. |
126 * to the buffer without invoking any destructor. |
| 133 * When \p targetbuf is not set, the destructors SHALL be invoked. |
127 * When @p targetbuf is not set, the destructors SHALL be invoked. |
| 134 * |
128 * |
| 135 * The function SHALL return the actual number of elements removed, which |
129 * The function SHALL return the actual number of elements removed, which |
| 136 * might be lower than \p num when going out of bounds. |
130 * might be lower than @p num when going out of bounds. |
| 137 */ |
131 */ |
| 138 cx_attr_nonnull_arg(1) |
|
| 139 cx_attr_access_w(4) |
|
| 140 size_t (*remove)( |
132 size_t (*remove)( |
| 141 struct cx_list_s *list, |
133 struct cx_list_s *list, |
| 142 size_t index, |
134 size_t index, |
| 143 size_t num, |
135 size_t num, |
| 144 void *targetbuf |
136 void *targetbuf |
| 145 ); |
137 ); |
| 146 |
138 |
| 147 /** |
139 /** |
| 148 * Member function for removing all elements. |
140 * Member function for removing all elements. |
| 149 */ |
141 */ |
| 150 cx_attr_nonnull |
|
| 151 void (*clear)(struct cx_list_s *list); |
142 void (*clear)(struct cx_list_s *list); |
| 152 |
143 |
| 153 /** |
144 /** |
| 154 * Member function for swapping two elements. |
145 * Member function for swapping two elements. |
| |
146 * |
| 155 * @see cx_list_default_swap() |
147 * @see cx_list_default_swap() |
| 156 */ |
148 */ |
| 157 cx_attr_nonnull |
|
| 158 int (*swap)( |
149 int (*swap)( |
| 159 struct cx_list_s *list, |
150 struct cx_list_s *list, |
| 160 size_t i, |
151 size_t i, |
| 161 size_t j |
152 size_t j |
| 162 ); |
153 ); |
| 163 |
154 |
| 164 /** |
155 /** |
| 165 * Member function for element lookup. |
156 * Member function for element lookup. |
| 166 */ |
157 */ |
| 167 cx_attr_nonnull |
|
| 168 cx_attr_nodiscard |
|
| 169 void *(*at)( |
158 void *(*at)( |
| 170 const struct cx_list_s *list, |
159 const struct cx_list_s *list, |
| 171 size_t index |
160 size_t index |
| 172 ); |
161 ); |
| 173 |
162 |
| 174 /** |
163 /** |
| 175 * Member function for finding and optionally removing an element. |
164 * Member function for finding and optionally removing an element. |
| 176 */ |
165 */ |
| 177 cx_attr_nonnull |
166 size_t (*find_remove)( |
| 178 cx_attr_nodiscard |
|
| 179 ssize_t (*find_remove)( |
|
| 180 struct cx_list_s *list, |
167 struct cx_list_s *list, |
| 181 const void *elem, |
168 const void *elem, |
| 182 bool remove |
169 bool remove |
| 183 ); |
170 ); |
| 184 |
171 |
| 185 /** |
172 /** |
| 186 * Member function for sorting the list in-place. |
173 * Member function for sorting the list. |
| |
174 * |
| 187 * @see cx_list_default_sort() |
175 * @see cx_list_default_sort() |
| 188 */ |
176 */ |
| 189 cx_attr_nonnull |
|
| 190 void (*sort)(struct cx_list_s *list); |
177 void (*sort)(struct cx_list_s *list); |
| 191 |
178 |
| 192 /** |
179 /** |
| 193 * Optional member function for comparing this list |
180 * Optional member function for comparing this list |
| 194 * to another list of the same type. |
181 * to another list of the same type. |
| 195 * If set to \c NULL, comparison won't be optimized. |
182 * If set to @c NULL, comparison won't be optimized. |
| 196 */ |
183 */ |
| 197 cx_attr_nonnull |
184 cx_attr_nonnull |
| 198 int (*compare)( |
185 int (*compare)( |
| 199 const struct cx_list_s *list, |
186 const struct cx_list_s *list, |
| 200 const struct cx_list_s *other |
187 const struct cx_list_s *other |
| 201 ); |
188 ); |
| 202 |
189 |
| 203 /** |
190 /** |
| 204 * Member function for reversing the order of the items. |
191 * Member function for reversing the order of the items. |
| 205 */ |
192 */ |
| 206 cx_attr_nonnull |
|
| 207 void (*reverse)(struct cx_list_s *list); |
193 void (*reverse)(struct cx_list_s *list); |
| 208 |
194 |
| 209 /** |
195 /** |
| 210 * Member function for returning an iterator pointing to the specified index. |
196 * Member function for returning an iterator pointing to the specified index. |
| 211 */ |
197 */ |
| 212 cx_attr_nonnull |
|
| 213 struct cx_iterator_s (*iterator)( |
198 struct cx_iterator_s (*iterator)( |
| 214 const struct cx_list_s *list, |
199 const struct cx_list_s *list, |
| 215 size_t index, |
200 size_t index, |
| 216 bool backward |
201 bool backward |
| 217 ); |
202 ); |
| 243 * Default implementation of a sorted insert. |
229 * Default implementation of a sorted insert. |
| 244 * |
230 * |
| 245 * This function uses the array insert function to insert consecutive groups |
231 * This function uses the array insert function to insert consecutive groups |
| 246 * of sorted data. |
232 * of sorted data. |
| 247 * |
233 * |
| 248 * The source data \em must already be sorted wrt. the list's compare function. |
234 * The source data @em must already be sorted wrt. the list's compare function. |
| 249 * |
235 * |
| 250 * Use this in your own list class if you do not want to implement an optimized |
236 * Use this in your own list class if you do not want to implement an optimized |
| 251 * version for your list. |
237 * version for your list. |
| 252 * |
238 * |
| 253 * @param list the list |
239 * @param list the list |
| 254 * @param sorted_data a pointer to the array of pre-sorted data to insert |
240 * @param sorted_data a pointer to the array of pre-sorted data to insert |
| 255 * @param n the number of elements to insert |
241 * @param n the number of elements to insert |
| 256 * @return the number of elements actually inserted |
242 * @return the number of elements actually inserted |
| 257 */ |
243 */ |
| 258 cx_attr_nonnull |
244 cx_attr_nonnull |
| |
245 cx_attr_export |
| 259 size_t cx_list_default_insert_sorted( |
246 size_t cx_list_default_insert_sorted( |
| 260 struct cx_list_s *list, |
247 struct cx_list_s *list, |
| 261 const void *sorted_data, |
248 const void *sorted_data, |
| 262 size_t n |
249 size_t n |
| 263 ); |
250 ); |
| 283 * version for your list. |
271 * version for your list. |
| 284 * |
272 * |
| 285 * @param list the list in which to swap |
273 * @param list the list in which to swap |
| 286 * @param i index of one element |
274 * @param i index of one element |
| 287 * @param j index of the other element |
275 * @param j index of the other element |
| 288 * @return zero on success, non-zero when indices are out of bounds or memory |
276 * @retval zero success |
| |
277 * @retval non-zero when indices are out of bounds or memory |
| 289 * allocation for the temporary buffer fails |
278 * allocation for the temporary buffer fails |
| 290 */ |
279 */ |
| 291 cx_attr_nonnull |
280 cx_attr_nonnull |
| |
281 cx_attr_export |
| 292 int cx_list_default_swap(struct cx_list_s *list, size_t i, size_t j); |
282 int cx_list_default_swap(struct cx_list_s *list, size_t i, size_t j); |
| 293 |
283 |
| 294 /** |
284 /** |
| |
285 * Initializes a list struct. |
| |
286 * |
| |
287 * Only use this function if you are creating your own list implementation. |
| |
288 * The purpose of this function is to be called in the initialization code |
| |
289 * of your list, to set certain members correctly. |
| |
290 * |
| |
291 * This is particularly important when you want your list to support |
| |
292 * #CX_STORE_POINTERS as @p elem_size. This function will wrap the list |
| |
293 * class accordingly and make sure that you can implement your list as if |
| |
294 * it was only storing objects and the wrapper will automatically enable |
| |
295 * the feature of storing pointers. |
| |
296 * |
| |
297 * @par Example |
| |
298 * |
| |
299 * @code |
| |
300 * CxList *myCustomListCreate( |
| |
301 * const CxAllocator *allocator, |
| |
302 * cx_compare_func comparator, |
| |
303 * size_t elem_size |
| |
304 * ) { |
| |
305 * if (allocator == NULL) { |
| |
306 * allocator = cxDefaultAllocator; |
| |
307 * } |
| |
308 * |
| |
309 * MyCustomList *list = cxCalloc(allocator, 1, sizeof(MyCustomList)); |
| |
310 * if (list == NULL) return NULL; |
| |
311 * |
| |
312 * // initialize |
| |
313 * cx_list_init((CxList*)list, &my_custom_list_class, |
| |
314 * allocator, comparator, elem_size); |
| |
315 * |
| |
316 * // ... some more custom stuff ... |
| |
317 * |
| |
318 * return (CxList *) list; |
| |
319 * } |
| |
320 * @endcode |
| |
321 * |
| |
322 * @param list the list to initialize |
| |
323 * @param cl the list class |
| |
324 * @param allocator the allocator for the elements |
| |
325 * @param comparator a compare function for the elements |
| |
326 * @param elem_size the size of one element |
| |
327 */ |
| |
328 cx_attr_nonnull_arg(1, 2, 3) |
| |
329 cx_attr_export |
| |
330 void cx_list_init( |
| |
331 struct cx_list_s *list, |
| |
332 struct cx_list_class_s *cl, |
| |
333 const struct cx_allocator_s *allocator, |
| |
334 cx_compare_func comparator, |
| |
335 size_t elem_size |
| |
336 ); |
| |
337 |
| |
338 /** |
| 295 * Common type for all list implementations. |
339 * Common type for all list implementations. |
| 296 */ |
340 */ |
| 297 typedef struct cx_list_s CxList; |
341 typedef struct cx_list_s CxList; |
| 298 |
|
| 299 /** |
|
| 300 * Advises the list to store copies of the objects (default mode of operation). |
|
| 301 * |
|
| 302 * Retrieving objects from this list will yield pointers to the copies stored |
|
| 303 * within this list. |
|
| 304 * |
|
| 305 * @param list the list |
|
| 306 * @see cxListStorePointers() |
|
| 307 */ |
|
| 308 cx_attr_nonnull |
|
| 309 void cxListStoreObjects(CxList *list); |
|
| 310 |
|
| 311 /** |
|
| 312 * Advises the list to only store pointers to the objects. |
|
| 313 * |
|
| 314 * Retrieving objects from this list will yield the original pointers stored. |
|
| 315 * |
|
| 316 * @note This function forcibly sets the element size to the size of a pointer. |
|
| 317 * Invoking this function on a non-empty list that already stores copies of |
|
| 318 * objects is undefined. |
|
| 319 * |
|
| 320 * @param list the list |
|
| 321 * @see cxListStoreObjects() |
|
| 322 */ |
|
| 323 cx_attr_nonnull |
|
| 324 void cxListStorePointers(CxList *list); |
|
| 325 |
|
| 326 /** |
|
| 327 * Returns true, if this list is storing pointers instead of the actual data. |
|
| 328 * |
|
| 329 * @param list |
|
| 330 * @return true, if this list is storing pointers |
|
| 331 * @see cxListStorePointers() |
|
| 332 */ |
|
| 333 cx_attr_nonnull |
|
| 334 static inline bool cxListIsStoringPointers(const CxList *list) { |
|
| 335 return list->collection.store_pointer; |
|
| 336 } |
|
| 337 |
342 |
| 338 /** |
343 /** |
| 339 * Returns the number of elements currently stored in the list. |
344 * Returns the number of elements currently stored in the list. |
| 340 * |
345 * |
| 341 * @param list the list |
346 * @param list the list |
| 349 /** |
354 /** |
| 350 * Adds an item to the end of the list. |
355 * Adds an item to the end of the list. |
| 351 * |
356 * |
| 352 * @param list the list |
357 * @param list the list |
| 353 * @param elem a pointer to the element to add |
358 * @param elem a pointer to the element to add |
| 354 * @return zero on success, non-zero on memory allocation failure |
359 * @retval zero success |
| |
360 * @retval non-zero memory allocation failure |
| 355 * @see cxListAddArray() |
361 * @see cxListAddArray() |
| 356 */ |
362 */ |
| 357 cx_attr_nonnull |
363 cx_attr_nonnull |
| 358 static inline int cxListAdd( |
364 static inline int cxListAdd( |
| 359 CxList *list, |
365 CxList *list, |
| 360 const void *elem |
366 const void *elem |
| 361 ) { |
367 ) { |
| |
368 list->collection.sorted = false; |
| 362 return list->cl->insert_element(list, list->collection.size, elem); |
369 return list->cl->insert_element(list, list->collection.size, elem); |
| 363 } |
370 } |
| 364 |
371 |
| 365 /** |
372 /** |
| 366 * Adds multiple items to the end of the list. |
373 * Adds multiple items to the end of the list. |
| 367 * |
374 * |
| 368 * This method is more efficient than invoking cxListAdd() multiple times. |
375 * This method is more efficient than invoking cxListAdd() multiple times. |
| 369 * |
376 * |
| 370 * If there is not enough memory to add all elements, the returned value is |
377 * If there is not enough memory to add all elements, the returned value is |
| 371 * less than \p n. |
378 * less than @p n. |
| 372 * |
379 * |
| 373 * If this list is storing pointers instead of objects \p array is expected to |
380 * If this list is storing pointers instead of objects @p array is expected to |
| 374 * be an array of pointers. |
381 * be an array of pointers. |
| 375 * |
382 * |
| 376 * @param list the list |
383 * @param list the list |
| 377 * @param array a pointer to the elements to add |
384 * @param array a pointer to the elements to add |
| 378 * @param n the number of elements to add |
385 * @param n the number of elements to add |
| 382 static inline size_t cxListAddArray( |
389 static inline size_t cxListAddArray( |
| 383 CxList *list, |
390 CxList *list, |
| 384 const void *array, |
391 const void *array, |
| 385 size_t n |
392 size_t n |
| 386 ) { |
393 ) { |
| |
394 list->collection.sorted = false; |
| 387 return list->cl->insert_array(list, list->collection.size, array, n); |
395 return list->cl->insert_array(list, list->collection.size, array, n); |
| 388 } |
396 } |
| 389 |
397 |
| 390 /** |
398 /** |
| 391 * Inserts an item at the specified index. |
399 * Inserts an item at the specified index. |
| 392 * |
400 * |
| 393 * If \p index equals the list \c size, this is effectively cxListAdd(). |
401 * If @p index equals the list @c size, this is effectively cxListAdd(). |
| 394 * |
402 * |
| 395 * @param list the list |
403 * @param list the list |
| 396 * @param index the index the element shall have |
404 * @param index the index the element shall have |
| 397 * @param elem a pointer to the element to add |
405 * @param elem a pointer to the element to add |
| 398 * @return zero on success, non-zero on memory allocation failure |
406 * @retval zero success |
| 399 * or when the index is out of bounds |
407 * @retval non-zero memory allocation failure or the index is out of bounds |
| 400 * @see cxListInsertAfter() |
408 * @see cxListInsertAfter() |
| 401 * @see cxListInsertBefore() |
409 * @see cxListInsertBefore() |
| 402 */ |
410 */ |
| 403 cx_attr_nonnull |
411 cx_attr_nonnull |
| 404 static inline int cxListInsert( |
412 static inline int cxListInsert( |
| 405 CxList *list, |
413 CxList *list, |
| 406 size_t index, |
414 size_t index, |
| 407 const void *elem |
415 const void *elem |
| 408 ) { |
416 ) { |
| |
417 list->collection.sorted = false; |
| 409 return list->cl->insert_element(list, index, elem); |
418 return list->cl->insert_element(list, index, elem); |
| 410 } |
419 } |
| 411 |
420 |
| 412 /** |
421 /** |
| 413 * Inserts an item into a sorted list. |
422 * Inserts an item into a sorted list. |
| 414 * |
423 * |
| |
424 * If the list is not sorted already, the behavior is undefined. |
| |
425 * |
| 415 * @param list the list |
426 * @param list the list |
| 416 * @param elem a pointer to the element to add |
427 * @param elem a pointer to the element to add |
| 417 * @return zero on success, non-zero on memory allocation failure |
428 * @retval zero success |
| |
429 * @retval non-zero memory allocation failure |
| 418 */ |
430 */ |
| 419 cx_attr_nonnull |
431 cx_attr_nonnull |
| 420 static inline int cxListInsertSorted( |
432 static inline int cxListInsertSorted( |
| 421 CxList *list, |
433 CxList *list, |
| 422 const void *elem |
434 const void *elem |
| 423 ) { |
435 ) { |
| |
436 list->collection.sorted = true; // guaranteed by definition |
| 424 const void *data = list->collection.store_pointer ? &elem : elem; |
437 const void *data = list->collection.store_pointer ? &elem : elem; |
| 425 return list->cl->insert_sorted(list, data, 1) == 0; |
438 return list->cl->insert_sorted(list, data, 1) == 0; |
| 426 } |
439 } |
| 427 |
440 |
| 428 /** |
441 /** |
| 429 * Inserts multiple items to the list at the specified index. |
442 * Inserts multiple items to the list at the specified index. |
| 430 * If \p index equals the list size, this is effectively cxListAddArray(). |
443 * If @p index equals the list size, this is effectively cxListAddArray(). |
| 431 * |
444 * |
| 432 * This method is usually more efficient than invoking cxListInsert() |
445 * This method is usually more efficient than invoking cxListInsert() |
| 433 * multiple times. |
446 * multiple times. |
| 434 * |
447 * |
| 435 * If there is not enough memory to add all elements, the returned value is |
448 * If there is not enough memory to add all elements, the returned value is |
| 436 * less than \p n. |
449 * less than @p n. |
| 437 * |
450 * |
| 438 * If this list is storing pointers instead of objects \p array is expected to |
451 * If this list is storing pointers instead of objects @p array is expected to |
| 439 * be an array of pointers. |
452 * be an array of pointers. |
| 440 * |
453 * |
| 441 * @param list the list |
454 * @param list the list |
| 442 * @param index the index where to add the elements |
455 * @param index the index where to add the elements |
| 443 * @param array a pointer to the elements to add |
456 * @param array a pointer to the elements to add |
| 449 CxList *list, |
462 CxList *list, |
| 450 size_t index, |
463 size_t index, |
| 451 const void *array, |
464 const void *array, |
| 452 size_t n |
465 size_t n |
| 453 ) { |
466 ) { |
| |
467 list->collection.sorted = false; |
| 454 return list->cl->insert_array(list, index, array, n); |
468 return list->cl->insert_array(list, index, array, n); |
| 455 } |
469 } |
| 456 |
470 |
| 457 /** |
471 /** |
| 458 * Inserts a sorted array into a sorted list. |
472 * Inserts a sorted array into a sorted list. |
| 459 * |
473 * |
| 460 * This method is usually more efficient than inserting each element separately, |
474 * This method is usually more efficient than inserting each element separately, |
| 461 * because consecutive chunks of sorted data are inserted in one pass. |
475 * because consecutive chunks of sorted data are inserted in one pass. |
| 462 * |
476 * |
| 463 * If there is not enough memory to add all elements, the returned value is |
477 * If there is not enough memory to add all elements, the returned value is |
| 464 * less than \p n. |
478 * less than @p n. |
| 465 * |
479 * |
| 466 * If this list is storing pointers instead of objects \p array is expected to |
480 * If this list is storing pointers instead of objects @p array is expected to |
| 467 * be an array of pointers. |
481 * be an array of pointers. |
| |
482 * |
| |
483 * If the list is not sorted already, the behavior is undefined. |
| 468 * |
484 * |
| 469 * @param list the list |
485 * @param list the list |
| 470 * @param array a pointer to the elements to add |
486 * @param array a pointer to the elements to add |
| 471 * @param n the number of elements to add |
487 * @param n the number of elements to add |
| 472 * @return the number of added elements |
488 * @return the number of added elements |
| 475 static inline size_t cxListInsertSortedArray( |
491 static inline size_t cxListInsertSortedArray( |
| 476 CxList *list, |
492 CxList *list, |
| 477 const void *array, |
493 const void *array, |
| 478 size_t n |
494 size_t n |
| 479 ) { |
495 ) { |
| |
496 list->collection.sorted = true; // guaranteed by definition |
| 480 return list->cl->insert_sorted(list, array, n); |
497 return list->cl->insert_sorted(list, array, n); |
| 481 } |
498 } |
| 482 |
499 |
| 483 /** |
500 /** |
| 484 * Inserts an element after the current location of the specified iterator. |
501 * Inserts an element after the current location of the specified iterator. |
| 485 * |
502 * |
| 486 * The used iterator remains operational, but all other active iterators should |
503 * The used iterator remains operational, but all other active iterators should |
| 487 * be considered invalidated. |
504 * be considered invalidated. |
| 488 * |
505 * |
| 489 * If \p iter is not a list iterator, the behavior is undefined. |
506 * If @p iter is not a list iterator, the behavior is undefined. |
| 490 * If \p iter is a past-the-end iterator, the new element gets appended to the list. |
507 * If @p iter is a past-the-end iterator, the new element gets appended to the list. |
| 491 * |
508 * |
| 492 * @param iter an iterator |
509 * @param iter an iterator |
| 493 * @param elem the element to insert |
510 * @param elem the element to insert |
| 494 * @return zero on success, non-zero on memory allocation failure |
511 * @retval zero success |
| |
512 * @retval non-zero memory allocation failure |
| 495 * @see cxListInsert() |
513 * @see cxListInsert() |
| 496 * @see cxListInsertBefore() |
514 * @see cxListInsertBefore() |
| 497 */ |
515 */ |
| 498 cx_attr_nonnull |
516 cx_attr_nonnull |
| 499 static inline int cxListInsertAfter( |
517 static inline int cxListInsertAfter( |
| 500 CxIterator *iter, |
518 CxIterator *iter, |
| 501 const void *elem |
519 const void *elem |
| 502 ) { |
520 ) { |
| 503 return ((struct cx_list_s *) iter->src_handle.m)->cl->insert_iter(iter, elem, 0); |
521 CxList* list = (CxList*)iter->src_handle.m; |
| |
522 list->collection.sorted = false; |
| |
523 return list->cl->insert_iter(iter, elem, 0); |
| 504 } |
524 } |
| 505 |
525 |
| 506 /** |
526 /** |
| 507 * Inserts an element before the current location of the specified iterator. |
527 * Inserts an element before the current location of the specified iterator. |
| 508 * |
528 * |
| 509 * The used iterator remains operational, but all other active iterators should |
529 * The used iterator remains operational, but all other active iterators should |
| 510 * be considered invalidated. |
530 * be considered invalidated. |
| 511 * |
531 * |
| 512 * If \p iter is not a list iterator, the behavior is undefined. |
532 * If @p iter is not a list iterator, the behavior is undefined. |
| 513 * If \p iter is a past-the-end iterator, the new element gets appended to the list. |
533 * If @p iter is a past-the-end iterator, the new element gets appended to the list. |
| 514 * |
534 * |
| 515 * @param iter an iterator |
535 * @param iter an iterator |
| 516 * @param elem the element to insert |
536 * @param elem the element to insert |
| 517 * @return zero on success, non-zero on memory allocation failure |
537 * @retval zero success |
| |
538 * @retval non-zero memory allocation failure |
| 518 * @see cxListInsert() |
539 * @see cxListInsert() |
| 519 * @see cxListInsertAfter() |
540 * @see cxListInsertAfter() |
| 520 */ |
541 */ |
| 521 cx_attr_nonnull |
542 cx_attr_nonnull |
| 522 static inline int cxListInsertBefore( |
543 static inline int cxListInsertBefore( |
| 523 CxIterator *iter, |
544 CxIterator *iter, |
| 524 const void *elem |
545 const void *elem |
| 525 ) { |
546 ) { |
| 526 return ((struct cx_list_s *) iter->src_handle.m)->cl->insert_iter(iter, elem, 1); |
547 CxList* list = (CxList*)iter->src_handle.m; |
| |
548 list->collection.sorted = false; |
| |
549 return list->cl->insert_iter(iter, elem, 1); |
| 527 } |
550 } |
| 528 |
551 |
| 529 /** |
552 /** |
| 530 * Removes the element at the specified index. |
553 * Removes the element at the specified index. |
| 531 * |
554 * |
| 532 * If an element destructor function is specified, it is called before |
555 * If an element destructor function is specified, it is called before |
| 533 * removing the element. |
556 * removing the element. |
| 534 * |
557 * |
| 535 * @param list the list |
558 * @param list the list |
| 536 * @param index the index of the element |
559 * @param index the index of the element |
| 537 * @return zero on success, non-zero if the index is out of bounds |
560 * @retval zero success |
| |
561 * @retval non-zero index out of bounds |
| 538 */ |
562 */ |
| 539 cx_attr_nonnull |
563 cx_attr_nonnull |
| 540 static inline int cxListRemove( |
564 static inline int cxListRemove( |
| 541 CxList *list, |
565 CxList *list, |
| 542 size_t index |
566 size_t index |
| 546 |
570 |
| 547 /** |
571 /** |
| 548 * Removes and returns the element at the specified index. |
572 * Removes and returns the element at the specified index. |
| 549 * |
573 * |
| 550 * No destructor is called and instead the element is copied to the |
574 * No destructor is called and instead the element is copied to the |
| 551 * \p targetbuf which MUST be large enough to hold the removed element. |
575 * @p targetbuf which MUST be large enough to hold the removed element. |
| 552 * |
576 * |
| 553 * @param list the list |
577 * @param list the list |
| 554 * @param index the index of the element |
578 * @param index the index of the element |
| 555 * @param targetbuf a buffer where to copy the element |
579 * @param targetbuf a buffer where to copy the element |
| 556 * @return zero on success, non-zero if the index is out of bounds |
580 * @retval zero success |
| |
581 * @retval non-zero index out of bounds |
| 557 */ |
582 */ |
| 558 cx_attr_nonnull |
583 cx_attr_nonnull |
| 559 cx_attr_access_w(3) |
584 cx_attr_access_w(3) |
| 560 static inline int cxListRemoveAndGet( |
585 static inline int cxListRemoveAndGet( |
| 561 CxList *list, |
586 CxList *list, |
| 632 * it is necessary. |
658 * it is necessary. |
| 633 * |
659 * |
| 634 * @param list the list |
660 * @param list the list |
| 635 * @param i the index of the first element |
661 * @param i the index of the first element |
| 636 * @param j the index of the second element |
662 * @param j the index of the second element |
| 637 * @return zero on success, non-zero if one of the indices is out of bounds |
663 * @retval zero success |
| |
664 * @retval non-zero one of the indices is out of bounds |
| |
665 * or the swap needed extra memory but allocation failed |
| 638 */ |
666 */ |
| 639 cx_attr_nonnull |
667 cx_attr_nonnull |
| 640 static inline int cxListSwap( |
668 static inline int cxListSwap( |
| 641 CxList *list, |
669 CxList *list, |
| 642 size_t i, |
670 size_t i, |
| 643 size_t j |
671 size_t j |
| 644 ) { |
672 ) { |
| |
673 list->collection.sorted = false; |
| 645 return list->cl->swap(list, i, j); |
674 return list->cl->swap(list, i, j); |
| 646 } |
675 } |
| 647 |
676 |
| 648 /** |
677 /** |
| 649 * Returns a pointer to the element at the specified index. |
678 * Returns a pointer to the element at the specified index. |
| 650 * |
679 * |
| 651 * @param list the list |
680 * @param list the list |
| 652 * @param index the index of the element |
681 * @param index the index of the element |
| 653 * @return a pointer to the element or \c NULL if the index is out of bounds |
682 * @return a pointer to the element or @c NULL if the index is out of bounds |
| 654 */ |
683 */ |
| 655 cx_attr_nonnull |
684 cx_attr_nonnull |
| 656 static inline void *cxListAt( |
685 static inline void *cxListAt( |
| 657 const CxList *list, |
686 const CxList *list, |
| 658 size_t index |
687 size_t index |
| 801 static inline CxIterator cxListMutBackwardsIterator(CxList *list) { |
832 static inline CxIterator cxListMutBackwardsIterator(CxList *list) { |
| 802 return cxListMutBackwardsIteratorAt(list, list->collection.size - 1); |
833 return cxListMutBackwardsIteratorAt(list, list->collection.size - 1); |
| 803 } |
834 } |
| 804 |
835 |
| 805 /** |
836 /** |
| 806 * Returns the index of the first element that equals \p elem. |
837 * Returns the index of the first element that equals @p elem. |
| 807 * |
838 * |
| 808 * Determining equality is performed by the list's comparator function. |
839 * Determining equality is performed by the list's comparator function. |
| 809 * |
840 * |
| 810 * @param list the list |
841 * @param list the list |
| 811 * @param elem the element to find |
842 * @param elem the element to find |
| 812 * @return the index of the element or a negative |
843 * @return the index of the element or the size of the list when the element is not found |
| 813 * value when the element is not found |
844 * @see cxListIndexValid() |
| 814 */ |
845 */ |
| 815 cx_attr_nonnull |
846 cx_attr_nonnull |
| 816 cx_attr_nodiscard |
847 cx_attr_nodiscard |
| 817 static inline ssize_t cxListFind( |
848 static inline size_t cxListFind( |
| 818 const CxList *list, |
849 const CxList *list, |
| 819 const void *elem |
850 const void *elem |
| 820 ) { |
851 ) { |
| 821 return list->cl->find_remove((CxList*)list, elem, false); |
852 return list->cl->find_remove((CxList*)list, elem, false); |
| 822 } |
853 } |
| 823 |
854 |
| 824 /** |
855 /** |
| 825 * Removes and returns the index of the first element that equals \p elem. |
856 * Checks if the specified index is within bounds. |
| |
857 * |
| |
858 * @param list the list |
| |
859 * @param index the index |
| |
860 * @retval true if the index is within bounds |
| |
861 * @retval false if the index is out of bounds |
| |
862 */ |
| |
863 cx_attr_nonnull |
| |
864 cx_attr_nodiscard |
| |
865 static inline bool cxListIndexValid(const CxList *list, size_t index) { |
| |
866 return index < list->collection.size; |
| |
867 } |
| |
868 |
| |
869 /** |
| |
870 * Removes and returns the index of the first element that equals @p elem. |
| 826 * |
871 * |
| 827 * Determining equality is performed by the list's comparator function. |
872 * Determining equality is performed by the list's comparator function. |
| 828 * |
873 * |
| 829 * @param list the list |
874 * @param list the list |
| 830 * @param elem the element to find and remove |
875 * @param elem the element to find and remove |
| 831 * @return the index of the now removed element or a negative |
876 * @return the index of the now removed element or the list size |
| 832 * value when the element is not found or could not be removed |
877 * when the element is not found or could not be removed |
| 833 */ |
878 * @see cxListIndexValid() |
| 834 cx_attr_nonnull |
879 */ |
| 835 static inline ssize_t cxListFindRemove( |
880 cx_attr_nonnull |
| |
881 static inline size_t cxListFindRemove( |
| 836 CxList *list, |
882 CxList *list, |
| 837 const void *elem |
883 const void *elem |
| 838 ) { |
884 ) { |
| 839 return list->cl->find_remove(list, elem, true); |
885 return list->cl->find_remove(list, elem, true); |
| 840 } |
886 } |
| 841 |
887 |
| 842 /** |
888 /** |
| 843 * Sorts the list in-place. |
889 * Sorts the list. |
| 844 * |
890 * |
| 845 * \remark The underlying sort algorithm is implementation defined. |
891 * @remark The underlying sort algorithm is implementation defined. |
| 846 * |
892 * |
| 847 * @param list the list |
893 * @param list the list |
| 848 */ |
894 */ |
| 849 cx_attr_nonnull |
895 cx_attr_nonnull |
| 850 static inline void cxListSort(CxList *list) { |
896 static inline void cxListSort(CxList *list) { |
| 851 list->cl->sort(list); |
897 list->cl->sort(list); |
| |
898 list->collection.sorted = true; |
| 852 } |
899 } |
| 853 |
900 |
| 854 /** |
901 /** |
| 855 * Reverses the order of the items. |
902 * Reverses the order of the items. |
| 856 * |
903 * |
| 857 * @param list the list |
904 * @param list the list |
| 858 */ |
905 */ |
| 859 cx_attr_nonnull |
906 cx_attr_nonnull |
| 860 static inline void cxListReverse(CxList *list) { |
907 static inline void cxListReverse(CxList *list) { |
| |
908 // still sorted, but not according to the cmp_func |
| |
909 list->collection.sorted = false; |
| 861 list->cl->reverse(list); |
910 list->cl->reverse(list); |
| 862 } |
911 } |
| 863 |
912 |
| 864 /** |
913 /** |
| 865 * Compares a list to another list of the same type. |
914 * Compares a list to another list of the same type. |
| 867 * First, the list sizes are compared. |
916 * First, the list sizes are compared. |
| 868 * If they match, the lists are compared element-wise. |
917 * If they match, the lists are compared element-wise. |
| 869 * |
918 * |
| 870 * @param list the list |
919 * @param list the list |
| 871 * @param other the list to compare to |
920 * @param other the list to compare to |
| 872 * @return zero, if both lists are equal element wise, |
921 * @retval zero both lists are equal element wise |
| 873 * negative if the first list is smaller, positive if the first list is larger |
922 * @retval negative the first list is smaller |
| 874 */ |
923 * or the first non-equal element in the first list is smaller |
| 875 cx_attr_nonnull |
924 * @retval positive the first list is larger |
| 876 cx_attr_nodiscard |
925 * or the first non-equal element in the first list is larger |
| |
926 */ |
| |
927 cx_attr_nonnull |
| |
928 cx_attr_nodiscard |
| |
929 cx_attr_export |
| 877 int cxListCompare( |
930 int cxListCompare( |
| 878 const CxList *list, |
931 const CxList *list, |
| 879 const CxList *other |
932 const CxList *other |
| 880 ); |
933 ); |
| 881 |
934 |
| 882 /** |
935 /** |
| 883 * Deallocates the memory of the specified list structure. |
936 * Deallocates the memory of the specified list structure. |
| 884 * |
937 * |
| 885 * Also calls the content destructor function for each element, if specified. |
938 * Also calls the content destructor functions for each element, if specified. |
| 886 * |
939 * |
| 887 * @param list the list which shall be freed |
940 * @param list the list which shall be freed |
| 888 */ |
941 */ |
| 889 static inline void cxListFree(CxList *list) { |
942 cx_attr_export |
| 890 if (list == NULL) return; |
943 void cxListFree(CxList *list); |
| 891 list->cl->deallocate(list); |
|
| 892 } |
|
| 893 |
944 |
| 894 /** |
945 /** |
| 895 * A shared instance of an empty list. |
946 * A shared instance of an empty list. |
| 896 * |
947 * |
| 897 * Writing to that list is not allowed. |
948 * Writing to that list is not allowed. |
| 898 */ |
949 * |
| |
950 * You can use this is a placeholder for initializing CxList pointers |
| |
951 * for which you do not want to reserve memory right from the beginning. |
| |
952 */ |
| |
953 cx_attr_export |
| 899 extern CxList *const cxEmptyList; |
954 extern CxList *const cxEmptyList; |
| 900 |
955 |
| 901 |
956 |
| 902 #ifdef __cplusplus |
957 #ifdef __cplusplus |
| 903 } // extern "C" |
958 } // extern "C" |