| 112:c3f2f16fa4b8 | 113:dde28a806552 |
|---|---|
| 37 #define UCX_LIST_H | 37 #define UCX_LIST_H |
| 38 | 38 |
| 39 #include "common.h" | 39 #include "common.h" |
| 40 #include "collection.h" | 40 #include "collection.h" |
| 41 | 41 |
| 42 #include <assert.h> | |
| 43 | |
| 44 #ifdef __cplusplus | 42 #ifdef __cplusplus |
| 45 extern "C" { | 43 extern "C" { |
| 46 #endif | 44 #endif |
| 47 | 45 |
| 48 /** | 46 /** |
| 83 /** | 81 /** |
| 84 * Member function for inserting a single element. | 82 * Member function for inserting a single element. |
| 85 * The data pointer may be @c NULL, in which case the function shall only allocate memory. | 83 * The data pointer may be @c NULL, in which case the function shall only allocate memory. |
| 86 * Returns a pointer to the allocated memory or @c NULL if allocation fails. | 84 * Returns a pointer to the allocated memory or @c NULL if allocation fails. |
| 87 */ | 85 */ |
| 88 void *(*insert_element)( | 86 void *(*insert_element)(struct cx_list_s *list, size_t index, const void *data); |
| 89 struct cx_list_s *list, | |
| 90 size_t index, | |
| 91 const void *data | |
| 92 ); | |
| 93 | 87 |
| 94 /** | 88 /** |
| 95 * Member function for inserting multiple elements. | 89 * Member function for inserting multiple elements. |
| 96 * | 90 * |
| 91 * The data pointer may be @c NULL, in which case the function shall only allocate memory. | |
| 92 * Returns the number of successfully inserted or allocated elements. | |
| 93 * | |
| 97 * @see cx_list_default_insert_array() | 94 * @see cx_list_default_insert_array() |
| 98 */ | 95 */ |
| 99 size_t (*insert_array)( | 96 size_t (*insert_array)(struct cx_list_s *list, size_t index, const void *data, size_t n); |
| 100 struct cx_list_s *list, | |
| 101 size_t index, | |
| 102 const void *data, | |
| 103 size_t n | |
| 104 ); | |
| 105 | 97 |
| 106 /** | 98 /** |
| 107 * Member function for inserting sorted elements into a sorted list. | 99 * Member function for inserting sorted elements into a sorted list. |
| 100 * Returns the number of successfully inserted elements. | |
| 108 * | 101 * |
| 109 * @see cx_list_default_insert_sorted() | 102 * @see cx_list_default_insert_sorted() |
| 110 */ | 103 */ |
| 111 size_t (*insert_sorted)( | 104 size_t (*insert_sorted)(struct cx_list_s *list, const void *sorted_data, size_t n); |
| 112 struct cx_list_s *list, | |
| 113 const void *sorted_data, | |
| 114 size_t n | |
| 115 ); | |
| 116 | 105 |
| 117 /** | 106 /** |
| 118 * Member function for inserting multiple elements if they do not exist. | 107 * Member function for inserting multiple elements if they do not exist. |
| 119 * | 108 * Implementations shall return the number of successfully processed elements |
| 109 * (including those which were not added because they are already contained). | |
| 120 * @see cx_list_default_insert_unique() | 110 * @see cx_list_default_insert_unique() |
| 121 */ | 111 */ |
| 122 size_t (*insert_unique)( | 112 size_t (*insert_unique)(struct cx_list_s *list, const void *sorted_data, size_t n); |
| 123 struct cx_list_s *list, | |
| 124 const void *sorted_data, | |
| 125 size_t n | |
| 126 ); | |
| 127 | 113 |
| 128 /** | 114 /** |
| 129 * Member function for inserting an element relative to an iterator position. | 115 * Member function for inserting an element relative to an iterator position. |
| 130 */ | 116 */ |
| 131 int (*insert_iter)( | 117 int (*insert_iter)(struct cx_iterator_s *iter, const void *elem, int prepend); |
| 132 struct cx_iterator_s *iter, | |
| 133 const void *elem, | |
| 134 int prepend | |
| 135 ); | |
| 136 | 118 |
| 137 /** | 119 /** |
| 138 * Member function for removing elements. | 120 * Member function for removing elements. |
| 139 * | 121 * |
| 140 * Implementations SHALL check if @p targetbuf is set and copy the elements | 122 * Implementations SHALL check if @p targetbuf is set and copy the elements |
| 142 * When @p targetbuf is not set, the destructors SHALL be invoked. | 124 * When @p targetbuf is not set, the destructors SHALL be invoked. |
| 143 * | 125 * |
| 144 * The function SHALL return the actual number of elements removed, which | 126 * The function SHALL return the actual number of elements removed, which |
| 145 * might be lower than @p num when going out of bounds. | 127 * might be lower than @p num when going out of bounds. |
| 146 */ | 128 */ |
| 147 size_t (*remove)( | 129 size_t (*remove)(struct cx_list_s *list, size_t index, size_t num, void *targetbuf); |
| 148 struct cx_list_s *list, | |
| 149 size_t index, | |
| 150 size_t num, | |
| 151 void *targetbuf | |
| 152 ); | |
| 153 | 130 |
| 154 /** | 131 /** |
| 155 * Member function for removing all elements. | 132 * Member function for removing all elements. |
| 156 */ | 133 */ |
| 157 void (*clear)(struct cx_list_s *list); | 134 void (*clear)(struct cx_list_s *list); |
| 159 /** | 136 /** |
| 160 * Member function for swapping two elements. | 137 * Member function for swapping two elements. |
| 161 * | 138 * |
| 162 * @see cx_list_default_swap() | 139 * @see cx_list_default_swap() |
| 163 */ | 140 */ |
| 164 int (*swap)( | 141 int (*swap)(struct cx_list_s *list, size_t i, size_t j); |
| 165 struct cx_list_s *list, | |
| 166 size_t i, | |
| 167 size_t j | |
| 168 ); | |
| 169 | 142 |
| 170 /** | 143 /** |
| 171 * Member function for element lookup. | 144 * Member function for element lookup. |
| 172 */ | 145 */ |
| 173 void *(*at)( | 146 void *(*at)(const struct cx_list_s *list, size_t index); |
| 174 const struct cx_list_s *list, | |
| 175 size_t index | |
| 176 ); | |
| 177 | 147 |
| 178 /** | 148 /** |
| 179 * Member function for finding and optionally removing an element. | 149 * Member function for finding and optionally removing an element. |
| 180 */ | 150 */ |
| 181 size_t (*find_remove)( | 151 size_t (*find_remove)(struct cx_list_s *list, const void *elem, bool remove); |
| 182 struct cx_list_s *list, | |
| 183 const void *elem, | |
| 184 bool remove | |
| 185 ); | |
| 186 | 152 |
| 187 /** | 153 /** |
| 188 * Member function for sorting the list. | 154 * Member function for sorting the list. |
| 189 * | 155 * |
| 190 * @see cx_list_default_sort() | 156 * @see cx_list_default_sort() |
| 194 /** | 160 /** |
| 195 * Optional member function for comparing this list | 161 * Optional member function for comparing this list |
| 196 * to another list of the same type. | 162 * to another list of the same type. |
| 197 * If set to @c NULL, the comparison won't be optimized. | 163 * If set to @c NULL, the comparison won't be optimized. |
| 198 */ | 164 */ |
| 199 int (*compare)( | 165 int (*compare)(const struct cx_list_s *list, const struct cx_list_s *other); |
| 200 const struct cx_list_s *list, | |
| 201 const struct cx_list_s *other | |
| 202 ); | |
| 203 | 166 |
| 204 /** | 167 /** |
| 205 * Member function for reversing the order of the items. | 168 * Member function for reversing the order of the items. |
| 206 */ | 169 */ |
| 207 void (*reverse)(struct cx_list_s *list); | 170 void (*reverse)(struct cx_list_s *list); |
| 208 | 171 |
| 209 /** | 172 /** |
| 173 * Optional member function for changing the capacity. | |
| 174 * If the list does not support overallocation, this can be set to @c NULL. | |
| 175 */ | |
| 176 int (*change_capacity)(struct cx_list_s *list, size_t new_capacity); | |
| 177 | |
| 178 /** | |
| 210 * Member function for returning an iterator pointing to the specified index. | 179 * Member function for returning an iterator pointing to the specified index. |
| 211 */ | 180 */ |
| 212 struct cx_iterator_s (*iterator)( | 181 struct cx_iterator_s (*iterator)(const struct cx_list_s *list, size_t index, bool backward); |
| 213 const struct cx_list_s *list, | |
| 214 size_t index, | |
| 215 bool backward | |
| 216 ); | |
| 217 }; | 182 }; |
| 218 | 183 |
| 219 /** | 184 /** |
| 220 * Common type for all list implementations. | 185 * Common type for all list implementations. |
| 221 */ | 186 */ |
| 227 * Writing to that list is not allowed. | 192 * Writing to that list is not allowed. |
| 228 * | 193 * |
| 229 * You can use this as a placeholder for initializing CxList pointers | 194 * You can use this as a placeholder for initializing CxList pointers |
| 230 * for which you do not want to reserve memory right from the beginning. | 195 * for which you do not want to reserve memory right from the beginning. |
| 231 */ | 196 */ |
| 232 cx_attr_export | 197 CX_EXPORT extern CxList *const cxEmptyList; |
| 233 extern CxList *const cxEmptyList; | |
| 234 | 198 |
| 235 /** | 199 /** |
| 236 * Default implementation of an array insert. | 200 * Default implementation of an array insert. |
| 237 * | 201 * |
| 238 * This function uses the element insert function for each element of the array. | 202 * This function uses the element insert function for each element of the array. |
| 245 * @param data a pointer to the array of data to insert | 209 * @param data a pointer to the array of data to insert |
| 246 * @param n the number of elements to insert | 210 * @param n the number of elements to insert |
| 247 * @return the number of elements actually inserted | 211 * @return the number of elements actually inserted |
| 248 */ | 212 */ |
| 249 cx_attr_nonnull | 213 cx_attr_nonnull |
| 250 cx_attr_export | 214 CX_EXPORT size_t cx_list_default_insert_array(struct cx_list_s *list, |
| 251 size_t cx_list_default_insert_array( | 215 size_t index, const void *data, size_t n); |
| 252 struct cx_list_s *list, | |
| 253 size_t index, | |
| 254 const void *data, | |
| 255 size_t n | |
| 256 ); | |
| 257 | 216 |
| 258 /** | 217 /** |
| 259 * Default implementation of a sorted insert. | 218 * Default implementation of a sorted insert. |
| 260 * | 219 * |
| 261 * This function uses the array insert function to insert consecutive groups | 220 * This function uses the array insert function to insert consecutive groups |
| 270 * @param sorted_data a pointer to the array of pre-sorted data to insert | 229 * @param sorted_data a pointer to the array of pre-sorted data to insert |
| 271 * @param n the number of elements to insert | 230 * @param n the number of elements to insert |
| 272 * @return the number of elements actually inserted | 231 * @return the number of elements actually inserted |
| 273 */ | 232 */ |
| 274 cx_attr_nonnull | 233 cx_attr_nonnull |
| 275 cx_attr_export | 234 CX_EXPORT size_t cx_list_default_insert_sorted(struct cx_list_s *list, |
| 276 size_t cx_list_default_insert_sorted( | 235 const void *sorted_data, size_t n); |
| 277 struct cx_list_s *list, | |
| 278 const void *sorted_data, | |
| 279 size_t n | |
| 280 ); | |
| 281 | 236 |
| 282 /** | 237 /** |
| 283 * Default implementation of an array insert where only elements are inserted when they don't exist in the list. | 238 * Default implementation of an array insert where only elements are inserted when they don't exist in the list. |
| 284 * | 239 * |
| 285 * This function is similar to cx_list_default_insert_sorted(), except it skips elements that are already in the list. | 240 * This function is similar to cx_list_default_insert_sorted(), except it skips elements that are already in the list. |
| 294 * @param sorted_data a pointer to the array of pre-sorted data to insert | 249 * @param sorted_data a pointer to the array of pre-sorted data to insert |
| 295 * @param n the number of elements to insert | 250 * @param n the number of elements to insert |
| 296 * @return the number of elements from the @p sorted_data that are definitely present in the list after this call | 251 * @return the number of elements from the @p sorted_data that are definitely present in the list after this call |
| 297 */ | 252 */ |
| 298 cx_attr_nonnull | 253 cx_attr_nonnull |
| 299 cx_attr_export | 254 CX_EXPORT size_t cx_list_default_insert_unique(struct cx_list_s *list, |
| 300 size_t cx_list_default_insert_unique( | 255 const void *sorted_data, size_t n); |
| 301 struct cx_list_s *list, | |
| 302 const void *sorted_data, | |
| 303 size_t n | |
| 304 ); | |
| 305 | 256 |
| 306 /** | 257 /** |
| 307 * Default unoptimized sort implementation. | 258 * Default unoptimized sort implementation. |
| 308 * | 259 * |
| 309 * This function will copy all data to an array, sort the array with standard | 260 * This function will copy all data to an array, sort the array with standard |
| 313 * version for your list. | 264 * version for your list. |
| 314 * | 265 * |
| 315 * @param list the list that shall be sorted | 266 * @param list the list that shall be sorted |
| 316 */ | 267 */ |
| 317 cx_attr_nonnull | 268 cx_attr_nonnull |
| 318 cx_attr_export | 269 CX_EXPORT void cx_list_default_sort(struct cx_list_s *list); |
| 319 void cx_list_default_sort(struct cx_list_s *list); | |
| 320 | 270 |
| 321 /** | 271 /** |
| 322 * Default unoptimized swap implementation. | 272 * Default unoptimized swap implementation. |
| 323 * | 273 * |
| 324 * Use this in your own list class if you do not want to implement an optimized | 274 * Use this in your own list class if you do not want to implement an optimized |
| 330 * @retval zero success | 280 * @retval zero success |
| 331 * @retval non-zero when indices are out of bounds or memory | 281 * @retval non-zero when indices are out of bounds or memory |
| 332 * allocation for the temporary buffer fails | 282 * allocation for the temporary buffer fails |
| 333 */ | 283 */ |
| 334 cx_attr_nonnull | 284 cx_attr_nonnull |
| 335 cx_attr_export | 285 CX_EXPORT int cx_list_default_swap(struct cx_list_s *list, size_t i, size_t j); |
| 336 int cx_list_default_swap(struct cx_list_s *list, size_t i, size_t j); | |
| 337 | 286 |
| 338 /** | 287 /** |
| 339 * Initializes a list struct. | 288 * Initializes a list struct. |
| 340 * | 289 * |
| 341 * Only use this function if you are creating your own list implementation. | 290 * Only use this function if you are creating your own list implementation. |
| 378 * @param allocator the allocator for the elements | 327 * @param allocator the allocator for the elements |
| 379 * @param comparator a compare function for the elements | 328 * @param comparator a compare function for the elements |
| 380 * @param elem_size the size of one element | 329 * @param elem_size the size of one element |
| 381 */ | 330 */ |
| 382 cx_attr_nonnull_arg(1, 2, 3) | 331 cx_attr_nonnull_arg(1, 2, 3) |
| 383 cx_attr_export | 332 CX_EXPORT void cx_list_init(struct cx_list_s *list, |
| 384 void cx_list_init( | 333 struct cx_list_class_s *cl, const struct cx_allocator_s *allocator, |
| 385 struct cx_list_s *list, | 334 cx_compare_func comparator, size_t elem_size); |
| 386 struct cx_list_class_s *cl, | |
| 387 const struct cx_allocator_s *allocator, | |
| 388 cx_compare_func comparator, | |
| 389 size_t elem_size | |
| 390 ); | |
| 391 | 335 |
| 392 /** | 336 /** |
| 393 * Returns the number of elements currently stored in the list. | 337 * Returns the number of elements currently stored in the list. |
| 394 * | 338 * |
| 395 * @param list the list | 339 * @param list the list |
| 396 * @return the number of currently stored elements | 340 * @return the number of currently stored elements |
| 397 */ | 341 */ |
| 398 cx_attr_nonnull | 342 cx_attr_nonnull |
| 399 static inline size_t cxListSize(const CxList *list) { | 343 CX_EXPORT size_t cxListSize(const CxList *list); |
| 400 return list->collection.size; | |
| 401 } | |
| 402 | 344 |
| 403 /** | 345 /** |
| 404 * Adds an item to the end of the list. | 346 * Adds an item to the end of the list. |
| 405 * | 347 * |
| 406 * @param list the list | 348 * @param list the list |
| 409 * @retval non-zero memory allocation failure | 351 * @retval non-zero memory allocation failure |
| 410 * @see cxListAddArray() | 352 * @see cxListAddArray() |
| 411 * @see cxListEmplace() | 353 * @see cxListEmplace() |
| 412 */ | 354 */ |
| 413 cx_attr_nonnull | 355 cx_attr_nonnull |
| 414 static inline int cxListAdd( | 356 CX_EXPORT int cxListAdd(CxList *list, const void *elem); |
| 415 CxList *list, | |
| 416 const void *elem | |
| 417 ) { | |
| 418 list->collection.sorted = false; | |
| 419 return list->cl->insert_element(list, list->collection.size, elem) == NULL; | |
| 420 } | |
| 421 | 357 |
| 422 /** | 358 /** |
| 423 * Adds multiple items to the end of the list. | 359 * Adds multiple items to the end of the list. |
| 424 * | 360 * |
| 425 * This method is more efficient than invoking cxListAdd() multiple times. | 361 * This method is more efficient than invoking cxListAdd() multiple times. |
| 432 * | 368 * |
| 433 * @param list the list | 369 * @param list the list |
| 434 * @param array a pointer to the elements to add | 370 * @param array a pointer to the elements to add |
| 435 * @param n the number of elements to add | 371 * @param n the number of elements to add |
| 436 * @return the number of added elements | 372 * @return the number of added elements |
| 437 */ | 373 * @see cxListEmplaceArray() |
| 438 cx_attr_nonnull | 374 */ |
| 439 static inline size_t cxListAddArray( | 375 cx_attr_nonnull |
| 440 CxList *list, | 376 CX_EXPORT size_t cxListAddArray(CxList *list, const void *array, size_t n); |
| 441 const void *array, | |
| 442 size_t n | |
| 443 ) { | |
| 444 list->collection.sorted = false; | |
| 445 return list->cl->insert_array(list, list->collection.size, array, n); | |
| 446 } | |
| 447 | 377 |
| 448 /** | 378 /** |
| 449 * Inserts an item at the specified index. | 379 * Inserts an item at the specified index. |
| 450 * | 380 * |
| 451 * If the @p index equals the list @c size, this is effectively cxListAdd(). | 381 * If the @p index equals the list @c size, this is effectively cxListAdd(). |
| 458 * @see cxListInsertAfter() | 388 * @see cxListInsertAfter() |
| 459 * @see cxListInsertBefore() | 389 * @see cxListInsertBefore() |
| 460 * @see cxListEmplaceAt() | 390 * @see cxListEmplaceAt() |
| 461 */ | 391 */ |
| 462 cx_attr_nonnull | 392 cx_attr_nonnull |
| 463 static inline int cxListInsert( | 393 CX_EXPORT int cxListInsert(CxList *list, size_t index, const void *elem); |
| 464 CxList *list, | |
| 465 size_t index, | |
| 466 const void *elem | |
| 467 ) { | |
| 468 list->collection.sorted = false; | |
| 469 return list->cl->insert_element(list, index, elem) == NULL; | |
| 470 } | |
| 471 | 394 |
| 472 /** | 395 /** |
| 473 * Allocates memory for an element at the specified index and returns a pointer to that memory. | 396 * Allocates memory for an element at the specified index and returns a pointer to that memory. |
| 474 * | 397 * |
| 475 * @remark When the list is storing pointers, this will return a @c void**. | 398 * @remark When the list is storing pointers, this will return a @c void**. |
| 476 * | 399 * |
| 477 * @param list the list | 400 * @param list the list |
| 478 * @param index the index where to emplace the element | 401 * @param index the index where to emplace the element |
| 479 * @return a pointer to the allocated memory; @c NULL when the operation fails, or the index is out-of-bounds | 402 * @return a pointer to the allocated memory; @c NULL when the operation fails, or the index is out-of-bounds |
| 480 * @see cxListEmplace() | 403 * @see cxListEmplace() |
| 404 * @see cxListEmplaceArrayAt() | |
| 481 * @see cxListInsert() | 405 * @see cxListInsert() |
| 482 */ | 406 */ |
| 483 cx_attr_nonnull | 407 cx_attr_nonnull |
| 484 static inline void *cxListEmplaceAt(CxList *list, size_t index) { | 408 CX_EXPORT void *cxListEmplaceAt(CxList *list, size_t index); |
| 485 list->collection.sorted = false; | |
| 486 return list->cl->insert_element(list, index, NULL); | |
| 487 } | |
| 488 | |
| 489 | 409 |
| 490 /** | 410 /** |
| 491 * Allocates memory for an element at the end of the list and returns a pointer to that memory. | 411 * Allocates memory for an element at the end of the list and returns a pointer to that memory. |
| 492 * | 412 * |
| 493 * @remark When the list is storing pointers, this will return a @c void**. | 413 * @remark When the list is storing pointers, this will return a @c void**. |
| 496 * @return a pointer to the allocated memory; @c NULL when the operation fails, or the index is out-of-bounds | 416 * @return a pointer to the allocated memory; @c NULL when the operation fails, or the index is out-of-bounds |
| 497 * @see cxListEmplaceAt() | 417 * @see cxListEmplaceAt() |
| 498 * @see cxListAdd() | 418 * @see cxListAdd() |
| 499 */ | 419 */ |
| 500 cx_attr_nonnull | 420 cx_attr_nonnull |
| 501 static inline void *cxListEmplace(CxList *list) { | 421 CX_EXPORT void *cxListEmplace(CxList *list); |
| 502 list->collection.sorted = false; | 422 |
| 503 return list->cl->insert_element(list, list->collection.size, NULL); | 423 /** |
| 504 } | 424 * Allocates memory for multiple elements and returns an iterator. |
| 425 * | |
| 426 * The iterator will only iterate over the successfully allocated elements. | |
| 427 * The @c elem_count attribute is set to that number, and the @c index attribute | |
| 428 * will range from zero to @c elem_count minus one. | |
| 429 * | |
| 430 * @remark When the list is storing pointers, the iterator will iterate over | |
| 431 * the @c void** elements. | |
| 432 * | |
| 433 * @param list the list | |
| 434 * @param index the index where to insert the new data | |
| 435 * @param n the number of elements for which to allocate the memory | |
| 436 * @return an iterator, iterating over the new memory | |
| 437 * @see cxListEmplaceAt() | |
| 438 * @see cxListInsertArray() | |
| 439 */ | |
| 440 cx_attr_nonnull | |
| 441 CX_EXPORT CxIterator cxListEmplaceArrayAt(CxList *list, size_t index, size_t n); | |
| 442 | |
| 443 /** | |
| 444 * Allocates memory for multiple elements and returns an iterator. | |
| 445 * | |
| 446 * The iterator will only iterate over the successfully allocated elements. | |
| 447 * The @c elem_count attribute is set to that number, and the @c index attribute | |
| 448 * will range from zero to @c elem_count minus one. | |
| 449 * | |
| 450 * @remark When the list is storing pointers, the iterator will iterate over | |
| 451 * the @c void** elements. | |
| 452 * | |
| 453 * @param list the list | |
| 454 * @param n the number of elements for which to allocate the memory | |
| 455 * @return an iterator, iterating over the new memory | |
| 456 * @see cxListEmplace() | |
| 457 * @see cxListAddArray() | |
| 458 */ | |
| 459 cx_attr_nonnull | |
| 460 CX_EXPORT CxIterator cxListEmplaceArray(CxList *list, size_t n); | |
| 505 | 461 |
| 506 /** | 462 /** |
| 507 * Inserts an item into a sorted list. | 463 * Inserts an item into a sorted list. |
| 508 * | 464 * |
| 509 * If the list is not sorted already, the behavior is undefined. | 465 * If the list is not sorted already, the behavior is undefined. |
| 512 * @param elem a pointer to the element to add | 468 * @param elem a pointer to the element to add |
| 513 * @retval zero success | 469 * @retval zero success |
| 514 * @retval non-zero memory allocation failure | 470 * @retval non-zero memory allocation failure |
| 515 */ | 471 */ |
| 516 cx_attr_nonnull | 472 cx_attr_nonnull |
| 517 static inline int cxListInsertSorted( | 473 CX_EXPORT int cxListInsertSorted(CxList *list, const void *elem); |
| 518 CxList *list, | 474 |
| 519 const void *elem | 475 /** |
| 520 ) { | 476 * Inserts an item into a list if it does not exist. |
| 521 assert(list->collection.sorted || list->collection.size == 0); | 477 * |
| 522 list->collection.sorted = true; | 478 * If the list is not sorted already, this function will check all elements |
| 523 const void *data = list->collection.store_pointer ? &elem : elem; | 479 * and append the new element when it was not found. |
| 524 return list->cl->insert_sorted(list, data, 1) == 0; | 480 * It is strongly recommended to use this function only on sorted lists, where |
| 525 } | 481 * the element, if it is not contained, is inserted at the correct position. |
| 526 | |
| 527 /** | |
| 528 * Inserts an item into a sorted list if it does not exist. | |
| 529 * | |
| 530 * If the list is not sorted already, the behavior is undefined. | |
| 531 * | 482 * |
| 532 * @param list the list | 483 * @param list the list |
| 533 * @param elem a pointer to the element to add | 484 * @param elem a pointer to the element to add |
| 534 * @retval zero success (also when the element was already in the list) | 485 * @retval zero success (also when the element was already in the list) |
| 535 * @retval non-zero memory allocation failure | 486 * @retval non-zero memory allocation failure |
| 536 */ | 487 */ |
| 537 cx_attr_nonnull | 488 cx_attr_nonnull |
| 538 static inline int cxListInsertUnique( | 489 CX_EXPORT int cxListInsertUnique(CxList *list, const void *elem); |
| 539 CxList *list, | |
| 540 const void *elem | |
| 541 ) { | |
| 542 assert(list->collection.sorted || list->collection.size == 0); | |
| 543 list->collection.sorted = true; | |
| 544 const void *data = list->collection.store_pointer ? &elem : elem; | |
| 545 return list->cl->insert_unique(list, data, 1) == 0; | |
| 546 } | |
| 547 | 490 |
| 548 /** | 491 /** |
| 549 * Inserts multiple items to the list at the specified index. | 492 * Inserts multiple items to the list at the specified index. |
| 550 * If the @p index equals the list size, this is effectively cxListAddArray(). | 493 * If the @p index equals the list size, this is effectively cxListAddArray(). |
| 551 * | 494 * |
| 561 * @param list the list | 504 * @param list the list |
| 562 * @param index the index where to add the elements | 505 * @param index the index where to add the elements |
| 563 * @param array a pointer to the elements to add | 506 * @param array a pointer to the elements to add |
| 564 * @param n the number of elements to add | 507 * @param n the number of elements to add |
| 565 * @return the number of added elements | 508 * @return the number of added elements |
| 566 */ | 509 * @see cxListEmplaceArrayAt() |
| 567 cx_attr_nonnull | 510 */ |
| 568 static inline size_t cxListInsertArray( | 511 cx_attr_nonnull |
| 569 CxList *list, | 512 CX_EXPORT size_t cxListInsertArray(CxList *list, size_t index, const void *array, size_t n); |
| 570 size_t index, | |
| 571 const void *array, | |
| 572 size_t n | |
| 573 ) { | |
| 574 list->collection.sorted = false; | |
| 575 return list->cl->insert_array(list, index, array, n); | |
| 576 } | |
| 577 | 513 |
| 578 /** | 514 /** |
| 579 * Inserts a sorted array into a sorted list. | 515 * Inserts a sorted array into a sorted list. |
| 580 * | 516 * |
| 581 * This method is usually more efficient than inserting each element separately | 517 * This method is usually more efficient than inserting each element separately |
| 593 * @param array a pointer to the elements to add | 529 * @param array a pointer to the elements to add |
| 594 * @param n the number of elements to add | 530 * @param n the number of elements to add |
| 595 * @return the number of added elements | 531 * @return the number of added elements |
| 596 */ | 532 */ |
| 597 cx_attr_nonnull | 533 cx_attr_nonnull |
| 598 static inline size_t cxListInsertSortedArray( | 534 CX_EXPORT size_t cxListInsertSortedArray(CxList *list, const void *array, size_t n); |
| 599 CxList *list, | 535 |
| 600 const void *array, | 536 /** |
| 601 size_t n | 537 * Inserts an array into a list, skipping duplicates. |
| 602 ) { | 538 * |
| 603 assert(list->collection.sorted || list->collection.size == 0); | 539 * The @p list does not need to be sorted (in contrast to cxListInsertSortedArray()). |
| 604 list->collection.sorted = true; | 540 * But it is strongly recommended to use this function only on sorted lists, |
| 605 return list->cl->insert_sorted(list, array, n); | 541 * because otherwise it will fall back to an inefficient algorithm which inserts |
| 606 } | 542 * all elements one by one. |
| 607 | 543 * If the @p list is not sorted, the @p array also does not need to be sorted. |
| 608 /** | 544 * But when the @p list is sorted, the @p array must also be sorted. |
| 609 * Inserts a sorted array into a sorted list, skipping duplicates. | |
| 610 * | 545 * |
| 611 * This method is usually more efficient than inserting each element separately | 546 * This method is usually more efficient than inserting each element separately |
| 612 * because consecutive chunks of sorted data are inserted in one pass. | 547 * because consecutive chunks of sorted data are inserted in one pass. |
| 613 * | 548 * |
| 614 * If there is not enough memory to add all elements, the returned value is | 549 * If there is not enough memory to add all elements, the returned value is |
| 621 * be @p n. | 556 * be @p n. |
| 622 * | 557 * |
| 623 * If this list is storing pointers instead of objects @p array is expected to | 558 * If this list is storing pointers instead of objects @p array is expected to |
| 624 * be an array of pointers. | 559 * be an array of pointers. |
| 625 * | 560 * |
| 626 * If the list is not sorted already, the behavior is undefined. | |
| 627 * This is also the case when the @p array is not sorted. | |
| 628 * | |
| 629 * @param list the list | 561 * @param list the list |
| 630 * @param array a pointer to the elements to add | 562 * @param array a pointer to the elements to add |
| 631 * @param n the number of elements to add | 563 * @param n the number of elements to add |
| 632 * @return the number of added elements | 564 * @return the number of added elements |
| 633 * | 565 * |
| 634 * @return the number of elements from the @p sorted_data that are definitely present in the list after this call | 566 * @return the number of elements from the @p sorted_data that are definitely present in the list after this call |
| 635 */ | 567 */ |
| 636 cx_attr_nonnull | 568 cx_attr_nonnull |
| 637 static inline size_t cxListInsertUniqueArray( | 569 CX_EXPORT size_t cxListInsertUniqueArray(CxList *list, const void *array, size_t n); |
| 638 CxList *list, | |
| 639 const void *array, | |
| 640 size_t n | |
| 641 ) { | |
| 642 assert(list->collection.sorted || list->collection.size == 0); | |
| 643 list->collection.sorted = true; | |
| 644 return list->cl->insert_unique(list, array, n); | |
| 645 } | |
| 646 | 570 |
| 647 /** | 571 /** |
| 648 * Inserts an element after the current location of the specified iterator. | 572 * Inserts an element after the current location of the specified iterator. |
| 649 * | 573 * |
| 650 * The used iterator remains operational, but all other active iterators should | 574 * The used iterator remains operational, but all other active iterators should |
| 659 * @retval non-zero memory allocation failure | 583 * @retval non-zero memory allocation failure |
| 660 * @see cxListInsert() | 584 * @see cxListInsert() |
| 661 * @see cxListInsertBefore() | 585 * @see cxListInsertBefore() |
| 662 */ | 586 */ |
| 663 cx_attr_nonnull | 587 cx_attr_nonnull |
| 664 static inline int cxListInsertAfter( | 588 CX_EXPORT int cxListInsertAfter(CxIterator *iter, const void *elem); |
| 665 CxIterator *iter, | |
| 666 const void *elem | |
| 667 ) { | |
| 668 CxList* list = (CxList*)iter->src_handle.m; | |
| 669 list->collection.sorted = false; | |
| 670 return list->cl->insert_iter(iter, elem, 0); | |
| 671 } | |
| 672 | 589 |
| 673 /** | 590 /** |
| 674 * Inserts an element before the current location of the specified iterator. | 591 * Inserts an element before the current location of the specified iterator. |
| 675 * | 592 * |
| 676 * The used iterator remains operational, but all other active iterators should | 593 * The used iterator remains operational, but all other active iterators should |
| 685 * @retval non-zero memory allocation failure | 602 * @retval non-zero memory allocation failure |
| 686 * @see cxListInsert() | 603 * @see cxListInsert() |
| 687 * @see cxListInsertAfter() | 604 * @see cxListInsertAfter() |
| 688 */ | 605 */ |
| 689 cx_attr_nonnull | 606 cx_attr_nonnull |
| 690 static inline int cxListInsertBefore( | 607 CX_EXPORT int cxListInsertBefore(CxIterator *iter, const void *elem); |
| 691 CxIterator *iter, | |
| 692 const void *elem | |
| 693 ) { | |
| 694 CxList* list = (CxList*)iter->src_handle.m; | |
| 695 list->collection.sorted = false; | |
| 696 return list->cl->insert_iter(iter, elem, 1); | |
| 697 } | |
| 698 | 608 |
| 699 /** | 609 /** |
| 700 * Removes the element at the specified index. | 610 * Removes the element at the specified index. |
| 701 * | 611 * |
| 702 * If an element destructor function is specified, it is called before | 612 * If an element destructor function is specified, it is called before |
| 706 * @param index the index of the element | 616 * @param index the index of the element |
| 707 * @retval zero success | 617 * @retval zero success |
| 708 * @retval non-zero index out of bounds | 618 * @retval non-zero index out of bounds |
| 709 */ | 619 */ |
| 710 cx_attr_nonnull | 620 cx_attr_nonnull |
| 711 static inline int cxListRemove( | 621 CX_EXPORT int cxListRemove(CxList *list, size_t index); |
| 712 CxList *list, | |
| 713 size_t index | |
| 714 ) { | |
| 715 return list->cl->remove(list, index, 1, NULL) == 0; | |
| 716 } | |
| 717 | 622 |
| 718 /** | 623 /** |
| 719 * Removes and returns the element at the specified index. | 624 * Removes and returns the element at the specified index. |
| 720 * | 625 * |
| 721 * No destructor is called, and instead the element is copied to the | 626 * No destructor is called, and instead the element is copied to the |
| 726 * @param index the index of the element | 631 * @param index the index of the element |
| 727 * @param targetbuf a buffer where to copy the element | 632 * @param targetbuf a buffer where to copy the element |
| 728 * @retval zero success | 633 * @retval zero success |
| 729 * @retval non-zero index out of bounds | 634 * @retval non-zero index out of bounds |
| 730 */ | 635 */ |
| 731 cx_attr_nonnull | 636 cx_attr_nonnull cx_attr_access_w(3) |
| 732 cx_attr_access_w(3) | 637 CX_EXPORT int cxListRemoveAndGet(CxList *list, size_t index, void *targetbuf); |
| 733 static inline int cxListRemoveAndGet( | |
| 734 CxList *list, | |
| 735 size_t index, | |
| 736 void *targetbuf | |
| 737 ) { | |
| 738 return list->cl->remove(list, index, 1, targetbuf) == 0; | |
| 739 } | |
| 740 | 638 |
| 741 /** | 639 /** |
| 742 * Removes and returns the first element of the list. | 640 * Removes and returns the first element of the list. |
| 743 * | 641 * |
| 744 * No destructor is called, and instead the element is copied to the | 642 * No destructor is called, and instead the element is copied to the |
| 750 * @retval zero success | 648 * @retval zero success |
| 751 * @retval non-zero the list is empty | 649 * @retval non-zero the list is empty |
| 752 * @see cxListPopFront() | 650 * @see cxListPopFront() |
| 753 * @see cxListRemoveAndGetLast() | 651 * @see cxListRemoveAndGetLast() |
| 754 */ | 652 */ |
| 755 cx_attr_nonnull | 653 cx_attr_nonnull cx_attr_access_w(2) |
| 756 cx_attr_access_w(2) | 654 CX_EXPORT int cxListRemoveAndGetFirst(CxList *list, void *targetbuf); |
| 757 static inline int cxListRemoveAndGetFirst( | |
| 758 CxList *list, | |
| 759 void *targetbuf | |
| 760 ) { | |
| 761 return list->cl->remove(list, 0, 1, targetbuf) == 0; | |
| 762 } | |
| 763 | 655 |
| 764 /** | 656 /** |
| 765 * Removes and returns the first element of the list. | 657 * Removes and returns the first element of the list. |
| 766 * | 658 * |
| 767 * Alias for cxListRemoveAndGetFirst(). | 659 * Alias for cxListRemoveAndGetFirst(). |
| 790 * @param list the list | 682 * @param list the list |
| 791 * @param targetbuf a buffer where to copy the element | 683 * @param targetbuf a buffer where to copy the element |
| 792 * @retval zero success | 684 * @retval zero success |
| 793 * @retval non-zero the list is empty | 685 * @retval non-zero the list is empty |
| 794 */ | 686 */ |
| 795 cx_attr_nonnull | 687 cx_attr_nonnull cx_attr_access_w(2) |
| 796 cx_attr_access_w(2) | 688 CX_EXPORT int cxListRemoveAndGetLast(CxList *list, void *targetbuf); |
| 797 static inline int cxListRemoveAndGetLast( | |
| 798 CxList *list, | |
| 799 void *targetbuf | |
| 800 ) { | |
| 801 // note: index may wrap - member function will catch that | |
| 802 return list->cl->remove(list, list->collection.size - 1, 1, targetbuf) == 0; | |
| 803 } | |
| 804 | 689 |
| 805 /** | 690 /** |
| 806 * Removes and returns the last element of the list. | 691 * Removes and returns the last element of the list. |
| 807 * | 692 * |
| 808 * Alias for cxListRemoveAndGetLast(). | 693 * Alias for cxListRemoveAndGetLast(). |
| 834 * @param index the index of the element | 719 * @param index the index of the element |
| 835 * @param num the number of elements to remove | 720 * @param num the number of elements to remove |
| 836 * @return the actual number of removed elements | 721 * @return the actual number of removed elements |
| 837 */ | 722 */ |
| 838 cx_attr_nonnull | 723 cx_attr_nonnull |
| 839 static inline size_t cxListRemoveArray( | 724 CX_EXPORT size_t cxListRemoveArray(CxList *list, size_t index, size_t num); |
| 840 CxList *list, | |
| 841 size_t index, | |
| 842 size_t num | |
| 843 ) { | |
| 844 return list->cl->remove(list, index, num, NULL); | |
| 845 } | |
| 846 | 725 |
| 847 /** | 726 /** |
| 848 * Removes and returns multiple elements starting at the specified index. | 727 * Removes and returns multiple elements starting at the specified index. |
| 849 * | 728 * |
| 850 * No destructor is called, and instead the elements are copied to the | 729 * No destructor is called, and instead the elements are copied to the |
| 855 * @param index the index of the element | 734 * @param index the index of the element |
| 856 * @param num the number of elements to remove | 735 * @param num the number of elements to remove |
| 857 * @param targetbuf a buffer where to copy the elements | 736 * @param targetbuf a buffer where to copy the elements |
| 858 * @return the actual number of removed elements | 737 * @return the actual number of removed elements |
| 859 */ | 738 */ |
| 860 cx_attr_nonnull | 739 cx_attr_nonnull cx_attr_access_w(4) |
| 861 cx_attr_access_w(4) | 740 CX_EXPORT size_t cxListRemoveArrayAndGet(CxList *list, size_t index, size_t num, void *targetbuf); |
| 862 static inline size_t cxListRemoveArrayAndGet( | |
| 863 CxList *list, | |
| 864 size_t index, | |
| 865 size_t num, | |
| 866 void *targetbuf | |
| 867 ) { | |
| 868 return list->cl->remove(list, index, num, targetbuf); | |
| 869 } | |
| 870 | 741 |
| 871 /** | 742 /** |
| 872 * Removes all elements from this list. | 743 * Removes all elements from this list. |
| 873 * | 744 * |
| 874 * If element destructor functions are specified, they are called for each | 745 * If element destructor functions are specified, they are called for each |
| 875 * element before removing them. | 746 * element before removing them. |
| 876 * | 747 * |
| 877 * @param list the list | 748 * @param list the list |
| 878 */ | 749 */ |
| 879 cx_attr_nonnull | 750 cx_attr_nonnull |
| 880 static inline void cxListClear(CxList *list) { | 751 CX_EXPORT void cxListClear(CxList *list); |
| 881 list->cl->clear(list); | |
| 882 list->collection.sorted = true; // empty lists are always sorted | |
| 883 } | |
| 884 | 752 |
| 885 /** | 753 /** |
| 886 * Swaps two items in the list. | 754 * Swaps two items in the list. |
| 887 * | 755 * |
| 888 * Implementations should only allocate temporary memory for the swap if | 756 * Implementations should only allocate temporary memory for the swap if |
| 894 * @retval zero success | 762 * @retval zero success |
| 895 * @retval non-zero one of the indices is out of bounds, | 763 * @retval non-zero one of the indices is out of bounds, |
| 896 * or the swap needed extra memory, but allocation failed | 764 * or the swap needed extra memory, but allocation failed |
| 897 */ | 765 */ |
| 898 cx_attr_nonnull | 766 cx_attr_nonnull |
| 899 static inline int cxListSwap( | 767 CX_EXPORT int cxListSwap(CxList *list, size_t i, size_t j); |
| 900 CxList *list, | |
| 901 size_t i, | |
| 902 size_t j | |
| 903 ) { | |
| 904 list->collection.sorted = false; | |
| 905 return list->cl->swap(list, i, j); | |
| 906 } | |
| 907 | 768 |
| 908 /** | 769 /** |
| 909 * Returns a pointer to the element at the specified index. | 770 * Returns a pointer to the element at the specified index. |
| 910 * | 771 * |
| 911 * If the list is storing pointers, returns the pointer stored at the specified index. | 772 * If the list is storing pointers, returns the pointer stored at the specified index. |
| 913 * @param list the list | 774 * @param list the list |
| 914 * @param index the index of the element | 775 * @param index the index of the element |
| 915 * @return a pointer to the element or @c NULL if the index is out of bounds | 776 * @return a pointer to the element or @c NULL if the index is out of bounds |
| 916 */ | 777 */ |
| 917 cx_attr_nonnull | 778 cx_attr_nonnull |
| 918 static inline void *cxListAt( | 779 CX_EXPORT void *cxListAt(const CxList *list, size_t index); |
| 919 const CxList *list, | |
| 920 size_t index | |
| 921 ) { | |
| 922 return list->cl->at(list, index); | |
| 923 } | |
| 924 | 780 |
| 925 /** | 781 /** |
| 926 * Returns a pointer to the first element. | 782 * Returns a pointer to the first element. |
| 927 * | 783 * |
| 928 * If the list is storing pointers, returns the first pointer stored in the list. | 784 * If the list is storing pointers, returns the first pointer stored in the list. |
| 929 * | 785 * |
| 930 * @param list the list | 786 * @param list the list |
| 931 * @return a pointer to the first element or @c NULL if the list is empty | 787 * @return a pointer to the first element or @c NULL if the list is empty |
| 932 */ | 788 */ |
| 933 cx_attr_nonnull | 789 cx_attr_nonnull |
| 934 static inline void *cxListFirst(const CxList *list) { | 790 CX_EXPORT void *cxListFirst(const CxList *list); |
| 935 return list->cl->at(list, 0); | |
| 936 } | |
| 937 | 791 |
| 938 /** | 792 /** |
| 939 * Returns a pointer to the last element. | 793 * Returns a pointer to the last element. |
| 940 * | 794 * |
| 941 * If the list is storing pointers, returns the last pointer stored in the list. | 795 * If the list is storing pointers, returns the last pointer stored in the list. |
| 942 * | 796 * |
| 943 * @param list the list | 797 * @param list the list |
| 944 * @return a pointer to the last element or @c NULL if the list is empty | 798 * @return a pointer to the last element or @c NULL if the list is empty |
| 945 */ | 799 */ |
| 946 cx_attr_nonnull | 800 cx_attr_nonnull |
| 947 static inline void *cxListLast(const CxList *list) { | 801 CX_EXPORT void *cxListLast(const CxList *list); |
| 948 return list->cl->at(list, list->collection.size - 1); | 802 |
| 949 } | 803 /** |
| 950 | 804 * Sets the element at the specified index in the list. |
| 951 /** | 805 * |
| 952 * Sets the element at the specified index in the list | 806 * This overwrites the element in-place without calling any destructor |
| 807 * on the overwritten element. | |
| 953 * | 808 * |
| 954 * @param list the list to set the element in | 809 * @param list the list to set the element in |
| 955 * @param index the index to set the element at | 810 * @param index the index to set the element at |
| 956 * @param elem element to set | 811 * @param elem element to set |
| 957 * @retval zero on success | 812 * @retval zero on success |
| 958 * @retval non-zero when index is out of bounds | 813 * @retval non-zero when index is out of bounds |
| 959 */ | 814 */ |
| 960 cx_attr_nonnull | 815 cx_attr_nonnull |
| 961 cx_attr_export | 816 CX_EXPORT int cxListSet(CxList *list, size_t index, const void *elem); |
| 962 int cxListSet( | |
| 963 CxList *list, | |
| 964 size_t index, | |
| 965 const void *elem | |
| 966 ); | |
| 967 | 817 |
| 968 /** | 818 /** |
| 969 * Returns an iterator pointing to the item at the specified index. | 819 * Returns an iterator pointing to the item at the specified index. |
| 970 * | 820 * |
| 971 * The returned iterator is position-aware. | 821 * The returned iterator is position-aware. |
| 975 * @param list the list | 825 * @param list the list |
| 976 * @param index the index where the iterator shall point at | 826 * @param index the index where the iterator shall point at |
| 977 * @return a new iterator | 827 * @return a new iterator |
| 978 */ | 828 */ |
| 979 cx_attr_nodiscard | 829 cx_attr_nodiscard |
| 980 static inline CxIterator cxListIteratorAt( | 830 CX_EXPORT CxIterator cxListIteratorAt(const CxList *list, size_t index); |
| 981 const CxList *list, | |
| 982 size_t index | |
| 983 ) { | |
| 984 if (list == NULL) list = cxEmptyList; | |
| 985 return list->cl->iterator(list, index, false); | |
| 986 } | |
| 987 | 831 |
| 988 /** | 832 /** |
| 989 * Returns a backwards iterator pointing to the item at the specified index. | 833 * Returns a backwards iterator pointing to the item at the specified index. |
| 990 * | 834 * |
| 991 * The returned iterator is position-aware. | 835 * The returned iterator is position-aware. |
| 995 * @param list the list | 839 * @param list the list |
| 996 * @param index the index where the iterator shall point at | 840 * @param index the index where the iterator shall point at |
| 997 * @return a new iterator | 841 * @return a new iterator |
| 998 */ | 842 */ |
| 999 cx_attr_nodiscard | 843 cx_attr_nodiscard |
| 1000 static inline CxIterator cxListBackwardsIteratorAt( | 844 CX_EXPORT CxIterator cxListBackwardsIteratorAt(const CxList *list, size_t index); |
| 1001 const CxList *list, | 845 |
| 1002 size_t index | 846 /** |
| 1003 ) { | 847 * Returns an iterator pointing to the first item of the list. |
| 1004 if (list == NULL) list = cxEmptyList; | |
| 1005 return list->cl->iterator(list, index, true); | |
| 1006 } | |
| 1007 | |
| 1008 /** | |
| 1009 * Returns a mutating iterator pointing to the item at the specified index. | |
| 1010 * | 848 * |
| 1011 * The returned iterator is position-aware. | 849 * The returned iterator is position-aware. |
| 1012 * | 850 * |
| 1013 * If the index is out of range or @p list is @c NULL, a past-the-end iterator will be returned. | 851 * If the list is empty or @c NULL, a past-the-end iterator will be returned. |
| 1014 * | 852 * |
| 1015 * @param list the list | 853 * @param list the list |
| 1016 * @param index the index where the iterator shall point at | |
| 1017 * @return a new iterator | 854 * @return a new iterator |
| 1018 */ | 855 */ |
| 1019 cx_attr_nodiscard | 856 cx_attr_nodiscard |
| 1020 cx_attr_export | 857 CX_EXPORT CxIterator cxListIterator(const CxList *list); |
| 1021 CxIterator cxListMutIteratorAt( | 858 |
| 1022 CxList *list, | 859 /** |
| 1023 size_t index | 860 * Returns a backwards iterator pointing to the last item of the list. |
| 1024 ); | |
| 1025 | |
| 1026 /** | |
| 1027 * Returns a mutating backwards iterator pointing to the item at the | |
| 1028 * specified index. | |
| 1029 * | 861 * |
| 1030 * The returned iterator is position-aware. | 862 * The returned iterator is position-aware. |
| 1031 * | 863 * |
| 1032 * If the index is out of range or @p list is @c NULL, a past-the-end iterator will be returned. | 864 * If the list is empty or @c NULL, a past-the-end iterator will be returned. |
| 1033 * | 865 * |
| 1034 * @param list the list | 866 * @param list the list |
| 1035 * @param index the index where the iterator shall point at | |
| 1036 * @return a new iterator | 867 * @return a new iterator |
| 1037 */ | 868 */ |
| 1038 cx_attr_nodiscard | 869 cx_attr_nodiscard |
| 1039 cx_attr_export | 870 CX_EXPORT CxIterator cxListBackwardsIterator(const CxList *list); |
| 1040 CxIterator cxListMutBackwardsIteratorAt( | |
| 1041 CxList *list, | |
| 1042 size_t index | |
| 1043 ); | |
| 1044 | |
| 1045 /** | |
| 1046 * Returns an iterator pointing to the first item of the list. | |
| 1047 * | |
| 1048 * The returned iterator is position-aware. | |
| 1049 * | |
| 1050 * If the list is empty or @c NULL, a past-the-end iterator will be returned. | |
| 1051 * | |
| 1052 * @param list the list | |
| 1053 * @return a new iterator | |
| 1054 */ | |
| 1055 cx_attr_nodiscard | |
| 1056 static inline CxIterator cxListIterator(const CxList *list) { | |
| 1057 if (list == NULL) list = cxEmptyList; | |
| 1058 return list->cl->iterator(list, 0, false); | |
| 1059 } | |
| 1060 | |
| 1061 /** | |
| 1062 * Returns a mutating iterator pointing to the first item of the list. | |
| 1063 * | |
| 1064 * The returned iterator is position-aware. | |
| 1065 * | |
| 1066 * If the list is empty or @c NULL, a past-the-end iterator will be returned. | |
| 1067 * | |
| 1068 * @param list the list | |
| 1069 * @return a new iterator | |
| 1070 */ | |
| 1071 cx_attr_nodiscard | |
| 1072 static inline CxIterator cxListMutIterator(CxList *list) { | |
| 1073 if (list == NULL) list = cxEmptyList; | |
| 1074 return cxListMutIteratorAt(list, 0); | |
| 1075 } | |
| 1076 | |
| 1077 | |
| 1078 /** | |
| 1079 * Returns a backwards iterator pointing to the last item of the list. | |
| 1080 * | |
| 1081 * The returned iterator is position-aware. | |
| 1082 * | |
| 1083 * If the list is empty or @c NULL, a past-the-end iterator will be returned. | |
| 1084 * | |
| 1085 * @param list the list | |
| 1086 * @return a new iterator | |
| 1087 */ | |
| 1088 cx_attr_nodiscard | |
| 1089 static inline CxIterator cxListBackwardsIterator(const CxList *list) { | |
| 1090 if (list == NULL) list = cxEmptyList; | |
| 1091 return list->cl->iterator(list, list->collection.size - 1, true); | |
| 1092 } | |
| 1093 | |
| 1094 /** | |
| 1095 * Returns a mutating backwards iterator pointing to the last item of the list. | |
| 1096 * | |
| 1097 * The returned iterator is position-aware. | |
| 1098 * | |
| 1099 * If the list is empty or @c NULL, a past-the-end iterator will be returned. | |
| 1100 * | |
| 1101 * @param list the list | |
| 1102 * @return a new iterator | |
| 1103 */ | |
| 1104 cx_attr_nodiscard | |
| 1105 static inline CxIterator cxListMutBackwardsIterator(CxList *list) { | |
| 1106 if (list == NULL) list = cxEmptyList; | |
| 1107 return cxListMutBackwardsIteratorAt(list, list->collection.size - 1); | |
| 1108 } | |
| 1109 | 871 |
| 1110 /** | 872 /** |
| 1111 * Returns the index of the first element that equals @p elem. | 873 * Returns the index of the first element that equals @p elem. |
| 1112 * | 874 * |
| 1113 * Determining equality is performed by the list's comparator function. | 875 * Determining equality is performed by the list's comparator function. |
| 1116 * @param elem the element to find | 878 * @param elem the element to find |
| 1117 * @return the index of the element or the size of the list when the element is not found | 879 * @return the index of the element or the size of the list when the element is not found |
| 1118 * @see cxListIndexValid() | 880 * @see cxListIndexValid() |
| 1119 * @see cxListContains() | 881 * @see cxListContains() |
| 1120 */ | 882 */ |
| 1121 cx_attr_nonnull | 883 cx_attr_nonnull cx_attr_nodiscard |
| 1122 cx_attr_nodiscard | 884 CX_EXPORT size_t cxListFind(const CxList *list, const void *elem); |
| 1123 static inline size_t cxListFind( | |
| 1124 const CxList *list, | |
| 1125 const void *elem | |
| 1126 ) { | |
| 1127 return list->cl->find_remove((CxList*)list, elem, false); | |
| 1128 } | |
| 1129 | 885 |
| 1130 /** | 886 /** |
| 1131 * Checks if the list contains the specified element. | 887 * Checks if the list contains the specified element. |
| 1132 * | 888 * |
| 1133 * The elements are compared with the list's comparator function. | 889 * The elements are compared with the list's comparator function. |
| 1136 * @param elem the element to find | 892 * @param elem the element to find |
| 1137 * @retval true if the element is contained | 893 * @retval true if the element is contained |
| 1138 * @retval false if the element is not contained | 894 * @retval false if the element is not contained |
| 1139 * @see cxListFind() | 895 * @see cxListFind() |
| 1140 */ | 896 */ |
| 1141 cx_attr_nonnull | 897 cx_attr_nonnull cx_attr_nodiscard |
| 1142 cx_attr_nodiscard | 898 CX_EXPORT bool cxListContains(const CxList* list, const void* elem); |
| 1143 static inline bool cxListContains( | |
| 1144 const CxList* list, | |
| 1145 const void* elem | |
| 1146 ) { | |
| 1147 return list->cl->find_remove((CxList*)list, elem, false) < list->collection.size; | |
| 1148 } | |
| 1149 | 899 |
| 1150 /** | 900 /** |
| 1151 * Checks if the specified index is within bounds. | 901 * Checks if the specified index is within bounds. |
| 1152 * | 902 * |
| 1153 * @param list the list | 903 * @param list the list |
| 1154 * @param index the index | 904 * @param index the index |
| 1155 * @retval true if the index is within bounds | 905 * @retval true if the index is within bounds |
| 1156 * @retval false if the index is out of bounds | 906 * @retval false if the index is out of bounds |
| 1157 */ | 907 */ |
| 1158 cx_attr_nonnull | 908 cx_attr_nonnull cx_attr_nodiscard |
| 1159 cx_attr_nodiscard | 909 CX_EXPORT bool cxListIndexValid(const CxList *list, size_t index); |
| 1160 static inline bool cxListIndexValid(const CxList *list, size_t index) { | |
| 1161 return index < list->collection.size; | |
| 1162 } | |
| 1163 | 910 |
| 1164 /** | 911 /** |
| 1165 * Removes and returns the index of the first element that equals @p elem. | 912 * Removes and returns the index of the first element that equals @p elem. |
| 1166 * | 913 * |
| 1167 * Determining equality is performed by the list's comparator function. | 914 * Determining equality is performed by the list's comparator function. |
| 1171 * @return the index of the now removed element or the list size | 918 * @return the index of the now removed element or the list size |
| 1172 * when the element is not found or could not be removed | 919 * when the element is not found or could not be removed |
| 1173 * @see cxListIndexValid() | 920 * @see cxListIndexValid() |
| 1174 */ | 921 */ |
| 1175 cx_attr_nonnull | 922 cx_attr_nonnull |
| 1176 static inline size_t cxListFindRemove( | 923 CX_EXPORT size_t cxListFindRemove(CxList *list, const void *elem); |
| 1177 CxList *list, | |
| 1178 const void *elem | |
| 1179 ) { | |
| 1180 return list->cl->find_remove(list, elem, true); | |
| 1181 } | |
| 1182 | 924 |
| 1183 /** | 925 /** |
| 1184 * Sorts the list. | 926 * Sorts the list. |
| 1185 * | 927 * |
| 1186 * @remark The underlying sort algorithm is implementation defined. | 928 * @remark The underlying sort algorithm is implementation defined. |
| 1187 * | 929 * |
| 1188 * @param list the list | 930 * @param list the list |
| 1189 */ | 931 */ |
| 1190 cx_attr_nonnull | 932 cx_attr_nonnull |
| 1191 static inline void cxListSort(CxList *list) { | 933 CX_EXPORT void cxListSort(CxList *list); |
| 1192 if (list->collection.sorted) return; | |
| 1193 list->cl->sort(list); | |
| 1194 list->collection.sorted = true; | |
| 1195 } | |
| 1196 | 934 |
| 1197 /** | 935 /** |
| 1198 * Reverses the order of the items. | 936 * Reverses the order of the items. |
| 1199 * | 937 * |
| 1200 * @param list the list | 938 * @param list the list |
| 1201 */ | 939 */ |
| 1202 cx_attr_nonnull | 940 cx_attr_nonnull |
| 1203 static inline void cxListReverse(CxList *list) { | 941 CX_EXPORT void cxListReverse(CxList *list); |
| 1204 // still sorted, but not according to the cmp_func | |
| 1205 list->collection.sorted = false; | |
| 1206 list->cl->reverse(list); | |
| 1207 } | |
| 1208 | 942 |
| 1209 /** | 943 /** |
| 1210 * Compares a list to another list of the same type. | 944 * Compares a list to another list of the same type. |
| 1211 * | 945 * |
| 1212 * First, the list sizes are compared. | 946 * First, the list sizes are compared. |
| 1213 * If they match, the lists are compared element-wise. | 947 * If they match, the lists are compared element-wise. |
| 1214 * | 948 * |
| 1215 * @param list the list | 949 * @param list the list |
| 1216 * @param other the list to compare to | 950 * @param other the list to compare to |
| 1217 * @retval zero both lists are equal element wise | 951 * @retval zero both lists are equal element wise |
| 1218 * @retval negative the first list is smaller | 952 * @retval negative the first list is smaller, |
| 1219 * or the first non-equal element in the first list is smaller | 953 * or the first non-equal element in the first list is smaller |
| 1220 * @retval positive the first list is larger | 954 * @retval positive the first list is larger |
| 1221 * or the first non-equal element in the first list is larger | 955 * or the first non-equal element in the first list is larger |
| 1222 */ | 956 */ |
| 1223 cx_attr_nonnull | 957 cx_attr_nonnull cx_attr_nodiscard |
| 1224 cx_attr_nodiscard | 958 CX_EXPORT int cxListCompare(const CxList *list, const CxList *other); |
| 1225 cx_attr_export | |
| 1226 int cxListCompare( | |
| 1227 const CxList *list, | |
| 1228 const CxList *other | |
| 1229 ); | |
| 1230 | 959 |
| 1231 /** | 960 /** |
| 1232 * Deallocates the memory of the specified list structure. | 961 * Deallocates the memory of the specified list structure. |
| 1233 * | 962 * |
| 1234 * Also calls the content destructor functions for each element, if specified. | 963 * Also calls the content destructor functions for each element, if specified. |
| 1235 * | 964 * |
| 1236 * @param list the list that shall be freed | 965 * @param list the list that shall be freed |
| 1237 */ | 966 */ |
| 1238 cx_attr_export | 967 CX_EXPORT void cxListFree(CxList *list); |
| 1239 void cxListFree(CxList *list); | 968 |
| 1240 | 969 |
| 970 /** | |
| 971 * Performs a deep clone of one list into another. | |
| 972 * | |
| 973 * If the destination list already contains elements, the cloned elements | |
| 974 * are appended to that list. | |
| 975 * | |
| 976 * @attention If the cloned elements need to be destroyed by a destructor | |
| 977 * function, you must make sure that the destination list also uses this | |
| 978 * destructor function. | |
| 979 * | |
| 980 * @param dst the destination list | |
| 981 * @param src the source list | |
| 982 * @param clone_func the clone function for the elements | |
| 983 * @param clone_allocator the allocator that is passed to the clone function | |
| 984 * @param data optional additional data that is passed to the clone function | |
| 985 * @retval zero when all elements were successfully cloned | |
| 986 * @retval non-zero when an allocation error occurred | |
| 987 * @see cxListCloneSimple() | |
| 988 */ | |
| 989 cx_attr_nonnull_arg(1, 2, 3) | |
| 990 CX_EXPORT int cxListClone(CxList *dst, const CxList *src, | |
| 991 cx_clone_func clone_func, const CxAllocator *clone_allocator, void *data); | |
| 992 | |
| 993 /** | |
| 994 * Clones elements from a list only if they are not present in another list. | |
| 995 * | |
| 996 * If the @p minuend does not contain duplicates, this is equivalent to adding | |
| 997 * the set difference to the destination list. | |
| 998 * | |
| 999 * This function is optimized for the case when both the @p minuend and the | |
| 1000 * @p subtrahend are sorted. | |
| 1001 * | |
| 1002 * @param dst the destination list | |
| 1003 * @param minuend the list to subtract elements from | |
| 1004 * @param subtrahend the elements that shall be subtracted | |
| 1005 * @param clone_func the clone function for the elements | |
| 1006 * @param clone_allocator the allocator that is passed to the clone function | |
| 1007 * @param data optional additional data that is passed to the clone function | |
| 1008 * @retval zero when the elements were successfully cloned | |
| 1009 * @retval non-zero when an allocation error occurred | |
| 1010 * @see cxListDifferenceSimple() | |
| 1011 */ | |
| 1012 cx_attr_nonnull_arg(1, 2, 3, 4) | |
| 1013 CX_EXPORT int cxListDifference(CxList *dst, | |
| 1014 const CxList *minuend, const CxList *subtrahend, | |
| 1015 cx_clone_func clone_func, const CxAllocator *clone_allocator, void *data); | |
| 1016 | |
| 1017 /** | |
| 1018 * Clones elements from a list only if they are also present in another list. | |
| 1019 * | |
| 1020 * This function is optimized for the case when both the @p src and the | |
| 1021 * @p other list are sorted. | |
| 1022 * | |
| 1023 * If the destination list already contains elements, the intersection is appended | |
| 1024 * to that list. | |
| 1025 * | |
| 1026 * @param dst the destination list | |
| 1027 * @param src the list to clone the elements from | |
| 1028 * @param other the list to check the elements for existence | |
| 1029 * @param clone_func the clone function for the elements | |
| 1030 * @param clone_allocator the allocator that is passed to the clone function | |
| 1031 * @param data optional additional data that is passed to the clone function | |
| 1032 * @retval zero when the elements were successfully cloned | |
| 1033 * @retval non-zero when an allocation error occurred | |
| 1034 * @see cxListIntersectionSimple() | |
| 1035 */ | |
| 1036 cx_attr_nonnull_arg(1, 2, 3, 4) | |
| 1037 CX_EXPORT int cxListIntersection(CxList *dst, const CxList *src, const CxList *other, | |
| 1038 cx_clone_func clone_func, const CxAllocator *clone_allocator, void *data); | |
| 1039 | |
| 1040 /** | |
| 1041 * Performs a deep clone of one list into another, skipping duplicates. | |
| 1042 * | |
| 1043 * This function is optimized for the case when both the @p src and the | |
| 1044 * @p other list are sorted. | |
| 1045 * In that case, the union will also be sorted. | |
| 1046 * | |
| 1047 * If the destination list already contains elements, the union is appended | |
| 1048 * to that list. In that case the destination is not necessarily sorted. | |
| 1049 * | |
| 1050 * @param dst the destination list | |
| 1051 * @param src the primary source list | |
| 1052 * @param other the other list, where elements are only cloned from | |
| 1053 * when they are not in @p src | |
| 1054 * @param clone_func the clone function for the elements | |
| 1055 * @param clone_allocator the allocator that is passed to the clone function | |
| 1056 * @param data optional additional data that is passed to the clone function | |
| 1057 * @retval zero when the elements were successfully cloned | |
| 1058 * @retval non-zero when an allocation error occurred | |
| 1059 * @see cxListUnionSimple() | |
| 1060 */ | |
| 1061 cx_attr_nonnull_arg(1, 2, 3, 4) | |
| 1062 CX_EXPORT int cxListUnion(CxList *dst, const CxList *src, const CxList *other, | |
| 1063 cx_clone_func clone_func, const CxAllocator *clone_allocator, void *data); | |
| 1064 | |
| 1065 /** | |
| 1066 * Performs a shallow clone of one list into another. | |
| 1067 * | |
| 1068 * This function uses the default allocator, if needed, and performs | |
| 1069 * shallow clones with @c memcpy(). | |
| 1070 * | |
| 1071 * If the destination list already contains elements, the cloned elements | |
| 1072 * are appended to that list. | |
| 1073 * | |
| 1074 * @attention If the cloned elements need to be destroyed by a destructor | |
| 1075 * function, you must make sure that the destination list also uses this | |
| 1076 * destructor function. | |
| 1077 * | |
| 1078 * @param dst the destination list | |
| 1079 * @param src the source list | |
| 1080 * @retval zero when all elements were successfully cloned | |
| 1081 * @retval non-zero when an allocation error occurred | |
| 1082 * @see cxListClone() | |
| 1083 */ | |
| 1084 cx_attr_nonnull | |
| 1085 CX_EXPORT int cxListCloneSimple(CxList *dst, const CxList *src); | |
| 1086 | |
| 1087 /** | |
| 1088 * Clones elements from a list only if they are not present in another list. | |
| 1089 * | |
| 1090 * This function uses the default allocator, if needed, and performs | |
| 1091 * shallow clones with @c memcpy(). | |
| 1092 * | |
| 1093 * If the @p minuend does not contain duplicates, this is equivalent to adding | |
| 1094 * the set difference to the destination list. | |
| 1095 * | |
| 1096 * This function is optimized for the case when both the @p minuend and the | |
| 1097 * @p subtrahend are sorted. | |
| 1098 * | |
| 1099 * @param dst the destination list | |
| 1100 * @param minuend the list to subtract elements from | |
| 1101 * @param subtrahend the elements that shall be subtracted | |
| 1102 * @retval zero when the elements were successfully cloned | |
| 1103 * @retval non-zero when an allocation error occurred | |
| 1104 * @see cxListDifference() | |
| 1105 */ | |
| 1106 cx_attr_nonnull | |
| 1107 CX_EXPORT int cxListDifferenceSimple(CxList *dst, | |
| 1108 const CxList *minuend, const CxList *subtrahend); | |
| 1109 | |
| 1110 /** | |
| 1111 * Clones elements from a list only if they are also present in another list. | |
| 1112 * | |
| 1113 * This function uses the default allocator, if needed, and performs | |
| 1114 * shallow clones with @c memcpy(). | |
| 1115 * | |
| 1116 * This function is optimized for the case when both the @p src and the | |
| 1117 * @p other list are sorted. | |
| 1118 * | |
| 1119 * If the destination list already contains elements, the intersection is appended | |
| 1120 * to that list. | |
| 1121 * | |
| 1122 * @param dst the destination list | |
| 1123 * @param src the list to clone the elements from | |
| 1124 * @param other the list to check the elements for existence | |
| 1125 * @retval zero when the elements were successfully cloned | |
| 1126 * @retval non-zero when an allocation error occurred | |
| 1127 * @see cxListIntersection() | |
| 1128 */ | |
| 1129 cx_attr_nonnull | |
| 1130 CX_EXPORT int cxListIntersectionSimple(CxList *dst, const CxList *src, const CxList *other); | |
| 1131 | |
| 1132 /** | |
| 1133 * Performs a deep clone of one list into another, skipping duplicates. | |
| 1134 * | |
| 1135 * This function uses the default allocator, if needed, and performs | |
| 1136 * shallow clones with @c memcpy(). | |
| 1137 * | |
| 1138 * This function is optimized for the case when both the @p src and the | |
| 1139 * @p other list are sorted. | |
| 1140 * In that case, the union will also be sorted. | |
| 1141 * | |
| 1142 * If the destination list already contains elements, the union is appended | |
| 1143 * to that list. In that case the destination is not necessarily sorted. | |
| 1144 * | |
| 1145 * @param dst the destination list | |
| 1146 * @param src the primary source list | |
| 1147 * @param other the other list, where elements are only cloned from | |
| 1148 * when they are not in @p src | |
| 1149 * @retval zero when the elements were successfully cloned | |
| 1150 * @retval non-zero when an allocation error occurred | |
| 1151 * @see cxListUnion() | |
| 1152 */ | |
| 1153 cx_attr_nonnull | |
| 1154 CX_EXPORT int cxListUnionSimple(CxList *dst, const CxList *src, const CxList *other); | |
| 1155 | |
| 1156 /** | |
| 1157 * Asks the list to reserve enough memory for a given total number of elements. | |
| 1158 * | |
| 1159 * List implementations are free to choose if reserving memory upfront makes | |
| 1160 * sense. | |
| 1161 * For example, array-based implementations usually do support reserving memory | |
| 1162 * for additional elements while linked lists usually don't. | |
| 1163 * | |
| 1164 * @note When the requested capacity is smaller than the current size, | |
| 1165 * this function returns zero without performing any action. | |
| 1166 * | |
| 1167 * @param list the list | |
| 1168 * @param capacity the expected total number of elements | |
| 1169 * @retval zero on success or when overallocation is not supported | |
| 1170 * @retval non-zero when an allocation error occurred | |
| 1171 * @see cxListShrink() | |
| 1172 */ | |
| 1173 cx_attr_nonnull | |
| 1174 CX_EXPORT int cxListReserve(CxList *list, size_t capacity); | |
| 1175 | |
| 1176 /** | |
| 1177 * Advises the list to free any overallocated memory. | |
| 1178 * | |
| 1179 * Lists that do not support overallocation simply return zero. | |
| 1180 * | |
| 1181 * This function usually returns zero, except for very special and custom | |
| 1182 * list and/or allocator implementations where freeing memory can fail. | |
| 1183 * | |
| 1184 * @param list the list | |
| 1185 * @return usually zero | |
| 1186 */ | |
| 1187 cx_attr_nonnull | |
| 1188 CX_EXPORT int cxListShrink(CxList *list); | |
| 1241 | 1189 |
| 1242 #ifdef __cplusplus | 1190 #ifdef __cplusplus |
| 1243 } // extern "C" | 1191 } // extern "C" |
| 1244 #endif | 1192 #endif |
| 1245 | 1193 |