src/ucx/cx/list.h

changeset 579
e10457d74fe1
parent 504
c094afcdfb27
equal deleted inserted replaced
578:eb48f716b31c 579:e10457d74fe1
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE. 26 * POSSIBILITY OF SUCH DAMAGE.
27 */ 27 */
28 /** 28 /**
29 * \file list.h 29 * @file list.h
30 * \brief Interface for list implementations. 30 * @brief Interface for list implementations.
31 * \author Mike Becker 31 * @author Mike Becker
32 * \author Olaf Wintermann 32 * @author Olaf Wintermann
33 * \version 3.0 33 * @copyright 2-Clause BSD License
34 * \copyright 2-Clause BSD License
35 */ 34 */
36 35
37 #ifndef UCX_LIST_H 36 #ifndef UCX_LIST_H
38 #define UCX_LIST_H 37 #define UCX_LIST_H
39 38
51 50
52 /** 51 /**
53 * Structure for holding the base data of a list. 52 * Structure for holding the base data of a list.
54 */ 53 */
55 struct cx_list_s { 54 struct cx_list_s {
56 CX_COLLECTION_MEMBERS 55 /**
56 * Common members for collections.
57 */
58 CX_COLLECTION_BASE;
57 /** 59 /**
58 * The list class definition. 60 * The list class definition.
59 */ 61 */
60 cx_list_class const *cl; 62 const cx_list_class *cl;
61 /** 63 /**
62 * The actual implementation in case the list class is delegating. 64 * The actual implementation in case the list class is delegating.
63 */ 65 */
64 cx_list_class const *climpl; 66 const cx_list_class *climpl;
65 }; 67 };
66 68
67 /** 69 /**
68 * The class definition for arbitrary lists. 70 * The class definition for arbitrary lists.
69 */ 71 */
70 struct cx_list_class_s { 72 struct cx_list_class_s {
71 /** 73 /**
72 * Destructor function. 74 * Destructor function.
73 * 75 *
74 * Implementations SHALL invoke the content destructor functions if provided 76 * Implementations SHALL invoke the content destructor functions if provided
75 * and SHALL deallocate the list memory, if an allocator is provided. 77 * and SHALL deallocate the entire list memory.
76 */ 78 */
77 void (*destructor)(struct cx_list_s *list); 79 void (*deallocate)(struct cx_list_s *list);
78 80
79 /** 81 /**
80 * Member function for inserting a single element. 82 * Member function for inserting a single element.
81 * Implementors SHOULD see to performant implementations for corner cases.
82 */ 83 */
83 int (*insert_element)( 84 int (*insert_element)(
84 struct cx_list_s *list, 85 struct cx_list_s *list,
85 size_t index, 86 size_t index,
86 void const *data 87 const void *data
87 ); 88 );
88 89
89 /** 90 /**
90 * Member function for inserting multiple elements. 91 * Member function for inserting multiple elements.
91 * Implementors SHOULD see to performant implementations for corner cases. 92 *
93 * @see cx_list_default_insert_array()
92 */ 94 */
93 size_t (*insert_array)( 95 size_t (*insert_array)(
94 struct cx_list_s *list, 96 struct cx_list_s *list,
95 size_t index, 97 size_t index,
96 void const *data, 98 const void *data,
97 size_t n 99 size_t n
98 ); 100 );
99 101
100 /** 102 /**
103 * Member function for inserting sorted elements into a sorted list.
104 *
105 * @see cx_list_default_insert_sorted()
106 */
107 size_t (*insert_sorted)(
108 struct cx_list_s *list,
109 const void *sorted_data,
110 size_t n
111 );
112
113 /**
101 * Member function for inserting an element relative to an iterator position. 114 * Member function for inserting an element relative to an iterator position.
102 */ 115 */
103 int (*insert_iter)( 116 int (*insert_iter)(
104 struct cx_mut_iterator_s *iter, 117 struct cx_iterator_s *iter,
105 void const *elem, 118 const void *elem,
106 int prepend 119 int prepend
107 ); 120 );
108 121
109 /** 122 /**
110 * Member function for removing an element. 123 * Member function for removing elements.
111 */ 124 *
112 int (*remove)( 125 * Implementations SHALL check if @p targetbuf is set and copy the elements
126 * to the buffer without invoking any destructor.
127 * When @p targetbuf is not set, the destructors SHALL be invoked.
128 *
129 * The function SHALL return the actual number of elements removed, which
130 * might be lower than @p num when going out of bounds.
131 */
132 size_t (*remove)(
113 struct cx_list_s *list, 133 struct cx_list_s *list,
114 size_t index 134 size_t index,
135 size_t num,
136 void *targetbuf
115 ); 137 );
116 138
117 /** 139 /**
118 * Member function for removing all elements. 140 * Member function for removing all elements.
119 */ 141 */
120 void (*clear)(struct cx_list_s *list); 142 void (*clear)(struct cx_list_s *list);
121 143
122 /** 144 /**
123 * Member function for swapping two elements. 145 * Member function for swapping two elements.
146 *
147 * @see cx_list_default_swap()
124 */ 148 */
125 int (*swap)( 149 int (*swap)(
126 struct cx_list_s *list, 150 struct cx_list_s *list,
127 size_t i, 151 size_t i,
128 size_t j 152 size_t j
130 154
131 /** 155 /**
132 * Member function for element lookup. 156 * Member function for element lookup.
133 */ 157 */
134 void *(*at)( 158 void *(*at)(
135 struct cx_list_s const *list, 159 const struct cx_list_s *list,
136 size_t index 160 size_t index
137 ); 161 );
138 162
139 /** 163 /**
140 * Member function for finding an element. 164 * Member function for finding and optionally removing an element.
141 */ 165 */
142 ssize_t (*find)( 166 size_t (*find_remove)(
143 struct cx_list_s const *list, 167 struct cx_list_s *list,
144 void const *elem 168 const void *elem,
169 bool remove
145 ); 170 );
146 171
147 /** 172 /**
148 * Member function for sorting the list in-place. 173 * Member function for sorting the list.
174 *
175 * @see cx_list_default_sort()
149 */ 176 */
150 void (*sort)(struct cx_list_s *list); 177 void (*sort)(struct cx_list_s *list);
151 178
152 /** 179 /**
153 * Member function for comparing this list to another list of the same type. 180 * Optional member function for comparing this list
154 */ 181 * to another list of the same type.
182 * If set to @c NULL, comparison won't be optimized.
183 */
184 cx_attr_nonnull
155 int (*compare)( 185 int (*compare)(
156 struct cx_list_s const *list, 186 const struct cx_list_s *list,
157 struct cx_list_s const *other 187 const struct cx_list_s *other
158 ); 188 );
159 189
160 /** 190 /**
161 * Member function for reversing the order of the items. 191 * Member function for reversing the order of the items.
162 */ 192 */
164 194
165 /** 195 /**
166 * Member function for returning an iterator pointing to the specified index. 196 * Member function for returning an iterator pointing to the specified index.
167 */ 197 */
168 struct cx_iterator_s (*iterator)( 198 struct cx_iterator_s (*iterator)(
169 struct cx_list_s const *list, 199 const struct cx_list_s *list,
170 size_t index, 200 size_t index,
171 bool backward 201 bool backward
172 ); 202 );
173 }; 203 };
174 204
175 /** 205 /**
206 * Default implementation of an array insert.
207 *
208 * This function uses the element insert function for each element of the array.
209 *
210 * Use this in your own list class if you do not want to implement an optimized
211 * version for your list.
212 *
213 * @param list the list
214 * @param index the index where to insert the data
215 * @param data a pointer to the array of data to insert
216 * @param n the number of elements to insert
217 * @return the number of elements actually inserted
218 */
219 cx_attr_nonnull
220 cx_attr_export
221 size_t cx_list_default_insert_array(
222 struct cx_list_s *list,
223 size_t index,
224 const void *data,
225 size_t n
226 );
227
228 /**
229 * Default implementation of a sorted insert.
230 *
231 * This function uses the array insert function to insert consecutive groups
232 * of sorted data.
233 *
234 * The source data @em must already be sorted wrt. the list's compare function.
235 *
236 * Use this in your own list class if you do not want to implement an optimized
237 * version for your list.
238 *
239 * @param list the list
240 * @param sorted_data a pointer to the array of pre-sorted data to insert
241 * @param n the number of elements to insert
242 * @return the number of elements actually inserted
243 */
244 cx_attr_nonnull
245 cx_attr_export
246 size_t cx_list_default_insert_sorted(
247 struct cx_list_s *list,
248 const void *sorted_data,
249 size_t n
250 );
251
252 /**
253 * Default unoptimized sort implementation.
254 *
255 * This function will copy all data to an array, sort the array with standard
256 * qsort, and then copy the data back to the list memory.
257 *
258 * Use this in your own list class if you do not want to implement an optimized
259 * version for your list.
260 *
261 * @param list the list that shall be sorted
262 */
263 cx_attr_nonnull
264 cx_attr_export
265 void cx_list_default_sort(struct cx_list_s *list);
266
267 /**
268 * Default unoptimized swap implementation.
269 *
270 * Use this in your own list class if you do not want to implement an optimized
271 * version for your list.
272 *
273 * @param list the list in which to swap
274 * @param i index of one element
275 * @param j index of the other element
276 * @retval zero success
277 * @retval non-zero when indices are out of bounds or memory
278 * allocation for the temporary buffer fails
279 */
280 cx_attr_nonnull
281 cx_attr_export
282 int cx_list_default_swap(struct cx_list_s *list, size_t i, size_t j);
283
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 /**
176 * Common type for all list implementations. 339 * Common type for all list implementations.
177 */ 340 */
178 typedef struct cx_list_s CxList; 341 typedef struct cx_list_s CxList;
179 342
180 /** 343 /**
181 * Advises the list to store copies of the objects (default mode of operation).
182 *
183 * Retrieving objects from this list will yield pointers to the copies stored
184 * within this list.
185 *
186 * @param list the list
187 * @see cxListStorePointers()
188 */
189 __attribute__((__nonnull__))
190 void cxListStoreObjects(CxList *list);
191
192 /**
193 * Advises the list to only store pointers to the objects.
194 *
195 * Retrieving objects from this list will yield the original pointers stored.
196 *
197 * @note This function forcibly sets the element size to the size of a pointer.
198 * Invoking this function on a non-empty list that already stores copies of
199 * objects is undefined.
200 *
201 * @param list the list
202 * @see cxListStoreObjects()
203 */
204 __attribute__((__nonnull__))
205 void cxListStorePointers(CxList *list);
206
207 /**
208 * Returns true, if this list is storing pointers instead of the actual data.
209 *
210 * @param list
211 * @return true, if this list is storing pointers
212 * @see cxListStorePointers()
213 */
214 __attribute__((__nonnull__))
215 static inline bool cxListIsStoringPointers(CxList const *list) {
216 return list->store_pointer;
217 }
218
219 /**
220 * Returns the number of elements currently stored in the list. 344 * Returns the number of elements currently stored in the list.
221 * 345 *
222 * @param list the list 346 * @param list the list
223 * @return the number of currently stored elements 347 * @return the number of currently stored elements
224 */ 348 */
225 __attribute__((__nonnull__)) 349 cx_attr_nonnull
226 static inline size_t cxListSize(CxList const *list) { 350 static inline size_t cxListSize(const CxList *list) {
227 return list->size; 351 return list->collection.size;
228 } 352 }
229 353
230 /** 354 /**
231 * Adds an item to the end of the list. 355 * Adds an item to the end of the list.
232 * 356 *
233 * @param list the list 357 * @param list the list
234 * @param elem a pointer to the element to add 358 * @param elem a pointer to the element to add
235 * @return zero on success, non-zero on memory allocation failure 359 * @retval zero success
360 * @retval non-zero memory allocation failure
236 * @see cxListAddArray() 361 * @see cxListAddArray()
237 */ 362 */
238 __attribute__((__nonnull__)) 363 cx_attr_nonnull
239 static inline int cxListAdd( 364 static inline int cxListAdd(
240 CxList *list, 365 CxList *list,
241 void const *elem 366 const void *elem
242 ) { 367 ) {
243 return list->cl->insert_element(list, list->size, elem); 368 list->collection.sorted = false;
369 return list->cl->insert_element(list, list->collection.size, elem);
244 } 370 }
245 371
246 /** 372 /**
247 * Adds multiple items to the end of the list. 373 * Adds multiple items to the end of the list.
248 * 374 *
249 * This method is more efficient than invoking cxListAdd() multiple times. 375 * This method is more efficient than invoking cxListAdd() multiple times.
250 * 376 *
251 * 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
252 * less than \p n. 378 * less than @p n.
253 * 379 *
254 * 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
255 * be an array of pointers. 381 * be an array of pointers.
256 * 382 *
257 * @param list the list 383 * @param list the list
258 * @param array a pointer to the elements to add 384 * @param array a pointer to the elements to add
259 * @param n the number of elements to add 385 * @param n the number of elements to add
260 * @return the number of added elements 386 * @return the number of added elements
261 */ 387 */
262 __attribute__((__nonnull__)) 388 cx_attr_nonnull
263 static inline size_t cxListAddArray( 389 static inline size_t cxListAddArray(
264 CxList *list, 390 CxList *list,
265 void const *array, 391 const void *array,
266 size_t n 392 size_t n
267 ) { 393 ) {
268 return list->cl->insert_array(list, list->size, array, n); 394 list->collection.sorted = false;
395 return list->cl->insert_array(list, list->collection.size, array, n);
269 } 396 }
270 397
271 /** 398 /**
272 * Inserts an item at the specified index. 399 * Inserts an item at the specified index.
273 * 400 *
274 * 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().
275 * 402 *
276 * @param list the list 403 * @param list the list
277 * @param index the index the element shall have 404 * @param index the index the element shall have
278 * @param elem a pointer to the element to add 405 * @param elem a pointer to the element to add
279 * @return zero on success, non-zero on memory allocation failure 406 * @retval zero success
280 * or when the index is out of bounds 407 * @retval non-zero memory allocation failure or the index is out of bounds
281 * @see cxListInsertAfter() 408 * @see cxListInsertAfter()
282 * @see cxListInsertBefore() 409 * @see cxListInsertBefore()
283 */ 410 */
284 __attribute__((__nonnull__)) 411 cx_attr_nonnull
285 static inline int cxListInsert( 412 static inline int cxListInsert(
286 CxList *list, 413 CxList *list,
287 size_t index, 414 size_t index,
288 void const *elem 415 const void *elem
289 ) { 416 ) {
417 list->collection.sorted = false;
290 return list->cl->insert_element(list, index, elem); 418 return list->cl->insert_element(list, index, elem);
291 } 419 }
292 420
293 /** 421 /**
422 * Inserts an item into a sorted list.
423 *
424 * If the list is not sorted already, the behavior is undefined.
425 *
426 * @param list the list
427 * @param elem a pointer to the element to add
428 * @retval zero success
429 * @retval non-zero memory allocation failure
430 */
431 cx_attr_nonnull
432 static inline int cxListInsertSorted(
433 CxList *list,
434 const void *elem
435 ) {
436 list->collection.sorted = true; // guaranteed by definition
437 const void *data = list->collection.store_pointer ? &elem : elem;
438 return list->cl->insert_sorted(list, data, 1) == 0;
439 }
440
441 /**
294 * Inserts multiple items to the list at the specified index. 442 * Inserts multiple items to the list at the specified index.
295 * If \p index equals the list size, this is effectively cxListAddArray(). 443 * If @p index equals the list size, this is effectively cxListAddArray().
296 * 444 *
297 * This method is usually more efficient than invoking cxListInsert() 445 * This method is usually more efficient than invoking cxListInsert()
298 * multiple times. 446 * multiple times.
299 * 447 *
300 * 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
301 * less than \p n. 449 * less than @p n.
302 * 450 *
303 * 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
304 * be an array of pointers. 452 * be an array of pointers.
305 * 453 *
306 * @param list the list 454 * @param list the list
307 * @param index the index where to add the elements 455 * @param index the index where to add the elements
308 * @param array a pointer to the elements to add 456 * @param array a pointer to the elements to add
309 * @param n the number of elements to add 457 * @param n the number of elements to add
310 * @return the number of added elements 458 * @return the number of added elements
311 */ 459 */
312 __attribute__((__nonnull__)) 460 cx_attr_nonnull
313 static inline size_t cxListInsertArray( 461 static inline size_t cxListInsertArray(
314 CxList *list, 462 CxList *list,
315 size_t index, 463 size_t index,
316 void const *array, 464 const void *array,
317 size_t n 465 size_t n
318 ) { 466 ) {
467 list->collection.sorted = false;
319 return list->cl->insert_array(list, index, array, n); 468 return list->cl->insert_array(list, index, array, n);
469 }
470
471 /**
472 * Inserts a sorted array into a sorted list.
473 *
474 * This method is usually more efficient than inserting each element separately,
475 * because consecutive chunks of sorted data are inserted in one pass.
476 *
477 * If there is not enough memory to add all elements, the returned value is
478 * less than @p n.
479 *
480 * If this list is storing pointers instead of objects @p array is expected to
481 * be an array of pointers.
482 *
483 * If the list is not sorted already, the behavior is undefined.
484 *
485 * @param list the list
486 * @param array a pointer to the elements to add
487 * @param n the number of elements to add
488 * @return the number of added elements
489 */
490 cx_attr_nonnull
491 static inline size_t cxListInsertSortedArray(
492 CxList *list,
493 const void *array,
494 size_t n
495 ) {
496 list->collection.sorted = true; // guaranteed by definition
497 return list->cl->insert_sorted(list, array, n);
320 } 498 }
321 499
322 /** 500 /**
323 * Inserts an element after the current location of the specified iterator. 501 * Inserts an element after the current location of the specified iterator.
324 * 502 *
325 * The used iterator remains operational, but all other active iterators should 503 * The used iterator remains operational, but all other active iterators should
326 * be considered invalidated. 504 * be considered invalidated.
327 * 505 *
328 * 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.
329 * 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.
330 * 508 *
331 * @param iter an iterator 509 * @param iter an iterator
332 * @param elem the element to insert 510 * @param elem the element to insert
333 * @return zero on success, non-zero on memory allocation failure 511 * @retval zero success
512 * @retval non-zero memory allocation failure
334 * @see cxListInsert() 513 * @see cxListInsert()
335 * @see cxListInsertBefore() 514 * @see cxListInsertBefore()
336 */ 515 */
337 __attribute__((__nonnull__)) 516 cx_attr_nonnull
338 static inline int cxListInsertAfter( 517 static inline int cxListInsertAfter(
339 CxMutIterator *iter, 518 CxIterator *iter,
340 void const *elem 519 const void *elem
341 ) { 520 ) {
342 return ((struct cx_list_s *) iter->src_handle)->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);
343 } 524 }
344 525
345 /** 526 /**
346 * Inserts an element before the current location of the specified iterator. 527 * Inserts an element before the current location of the specified iterator.
347 * 528 *
348 * The used iterator remains operational, but all other active iterators should 529 * The used iterator remains operational, but all other active iterators should
349 * be considered invalidated. 530 * be considered invalidated.
350 * 531 *
351 * 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.
352 * 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.
353 * 534 *
354 * @param iter an iterator 535 * @param iter an iterator
355 * @param elem the element to insert 536 * @param elem the element to insert
356 * @return zero on success, non-zero on memory allocation failure 537 * @retval zero success
538 * @retval non-zero memory allocation failure
357 * @see cxListInsert() 539 * @see cxListInsert()
358 * @see cxListInsertAfter() 540 * @see cxListInsertAfter()
359 */ 541 */
360 __attribute__((__nonnull__)) 542 cx_attr_nonnull
361 static inline int cxListInsertBefore( 543 static inline int cxListInsertBefore(
362 CxMutIterator *iter, 544 CxIterator *iter,
363 void const *elem 545 const void *elem
364 ) { 546 ) {
365 return ((struct cx_list_s *) iter->src_handle)->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);
366 } 550 }
367 551
368 /** 552 /**
369 * Removes the element at the specified index. 553 * Removes the element at the specified index.
370 * 554 *
371 * If an element destructor function is specified, it is called before 555 * If an element destructor function is specified, it is called before
372 * removing the element. 556 * removing the element.
373 * 557 *
374 * @param list the list 558 * @param list the list
375 * @param index the index of the element 559 * @param index the index of the element
376 * @return zero on success, non-zero if the index is out of bounds 560 * @retval zero success
377 */ 561 * @retval non-zero index out of bounds
378 __attribute__((__nonnull__)) 562 */
563 cx_attr_nonnull
379 static inline int cxListRemove( 564 static inline int cxListRemove(
380 CxList *list, 565 CxList *list,
381 size_t index 566 size_t index
382 ) { 567 ) {
383 return list->cl->remove(list, index); 568 return list->cl->remove(list, index, 1, NULL) == 0;
569 }
570
571 /**
572 * Removes and returns the element at the specified index.
573 *
574 * No destructor is called and instead the element is copied to the
575 * @p targetbuf which MUST be large enough to hold the removed element.
576 *
577 * @param list the list
578 * @param index the index of the element
579 * @param targetbuf a buffer where to copy the element
580 * @retval zero success
581 * @retval non-zero index out of bounds
582 */
583 cx_attr_nonnull
584 cx_attr_access_w(3)
585 static inline int cxListRemoveAndGet(
586 CxList *list,
587 size_t index,
588 void *targetbuf
589 ) {
590 return list->cl->remove(list, index, 1, targetbuf) == 0;
591 }
592
593 /**
594 * Removes multiple element starting at the specified index.
595 *
596 * If an element destructor function is specified, it is called for each
597 * element. It is guaranteed that the destructor is called before removing
598 * the element, however, due to possible optimizations it is neither guaranteed
599 * that the destructors are invoked for all elements before starting to remove
600 * them, nor that the element is removed immediately after the destructor call
601 * before proceeding to the next element.
602 *
603 * @param list the list
604 * @param index the index of the element
605 * @param num the number of elements to remove
606 * @return the actual number of removed elements
607 */
608 cx_attr_nonnull
609 static inline size_t cxListRemoveArray(
610 CxList *list,
611 size_t index,
612 size_t num
613 ) {
614 return list->cl->remove(list, index, num, NULL);
615 }
616
617 /**
618 * Removes and returns multiple element starting at the specified index.
619 *
620 * No destructor is called and instead the elements are copied to the
621 * @p targetbuf which MUST be large enough to hold all removed elements.
622 *
623 * @param list the list
624 * @param index the index of the element
625 * @param num the number of elements to remove
626 * @param targetbuf a buffer where to copy the elements
627 * @return the actual number of removed elements
628 */
629 cx_attr_nonnull
630 cx_attr_access_w(4)
631 static inline size_t cxListRemoveArrayAndGet(
632 CxList *list,
633 size_t index,
634 size_t num,
635 void *targetbuf
636 ) {
637 return list->cl->remove(list, index, num, targetbuf);
384 } 638 }
385 639
386 /** 640 /**
387 * Removes all elements from this list. 641 * Removes all elements from this list.
388 * 642 *
389 * If an element destructor function is specified, it is called for each 643 * If element destructor functions are specified, they are called for each
390 * element before removing them. 644 * element before removing them.
391 * 645 *
392 * @param list the list 646 * @param list the list
393 */ 647 */
394 __attribute__((__nonnull__)) 648 cx_attr_nonnull
395 static inline void cxListClear(CxList *list) { 649 static inline void cxListClear(CxList *list) {
650 list->collection.sorted = true; // empty lists are always sorted
396 list->cl->clear(list); 651 list->cl->clear(list);
397 } 652 }
398 653
399 /** 654 /**
400 * Swaps two items in the list. 655 * Swaps two items in the list.
403 * it is necessary. 658 * it is necessary.
404 * 659 *
405 * @param list the list 660 * @param list the list
406 * @param i the index of the first element 661 * @param i the index of the first element
407 * @param j the index of the second element 662 * @param j the index of the second element
408 * @return zero on success, non-zero if one of the indices is out of bounds 663 * @retval zero success
409 */ 664 * @retval non-zero one of the indices is out of bounds
410 __attribute__((__nonnull__)) 665 * or the swap needed extra memory but allocation failed
666 */
667 cx_attr_nonnull
411 static inline int cxListSwap( 668 static inline int cxListSwap(
412 CxList *list, 669 CxList *list,
413 size_t i, 670 size_t i,
414 size_t j 671 size_t j
415 ) { 672 ) {
673 list->collection.sorted = false;
416 return list->cl->swap(list, i, j); 674 return list->cl->swap(list, i, j);
417 } 675 }
418 676
419 /** 677 /**
420 * Returns a pointer to the element at the specified index. 678 * Returns a pointer to the element at the specified index.
421 * 679 *
422 * @param list the list 680 * @param list the list
423 * @param index the index of the element 681 * @param index the index of the element
424 * @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
425 */ 683 */
426 __attribute__((__nonnull__)) 684 cx_attr_nonnull
427 static inline void *cxListAt( 685 static inline void *cxListAt(
428 CxList *list, 686 const CxList *list,
429 size_t index 687 size_t index
430 ) { 688 ) {
431 return list->cl->at(list, index); 689 return list->cl->at(list, index);
432 } 690 }
433 691
440 * 698 *
441 * @param list the list 699 * @param list the list
442 * @param index the index where the iterator shall point at 700 * @param index the index where the iterator shall point at
443 * @return a new iterator 701 * @return a new iterator
444 */ 702 */
445 __attribute__((__nonnull__, __warn_unused_result__)) 703 cx_attr_nonnull
704 cx_attr_nodiscard
446 static inline CxIterator cxListIteratorAt( 705 static inline CxIterator cxListIteratorAt(
447 CxList const *list, 706 const CxList *list,
448 size_t index 707 size_t index
449 ) { 708 ) {
450 return list->cl->iterator(list, index, false); 709 return list->cl->iterator(list, index, false);
451 } 710 }
452 711
459 * 718 *
460 * @param list the list 719 * @param list the list
461 * @param index the index where the iterator shall point at 720 * @param index the index where the iterator shall point at
462 * @return a new iterator 721 * @return a new iterator
463 */ 722 */
464 __attribute__((__nonnull__, __warn_unused_result__)) 723 cx_attr_nonnull
724 cx_attr_nodiscard
465 static inline CxIterator cxListBackwardsIteratorAt( 725 static inline CxIterator cxListBackwardsIteratorAt(
466 CxList const *list, 726 const CxList *list,
467 size_t index 727 size_t index
468 ) { 728 ) {
469 return list->cl->iterator(list, index, true); 729 return list->cl->iterator(list, index, true);
470 } 730 }
471 731
478 * 738 *
479 * @param list the list 739 * @param list the list
480 * @param index the index where the iterator shall point at 740 * @param index the index where the iterator shall point at
481 * @return a new iterator 741 * @return a new iterator
482 */ 742 */
483 __attribute__((__nonnull__, __warn_unused_result__)) 743 cx_attr_nonnull
484 CxMutIterator cxListMutIteratorAt( 744 cx_attr_nodiscard
745 cx_attr_export
746 CxIterator cxListMutIteratorAt(
485 CxList *list, 747 CxList *list,
486 size_t index 748 size_t index
487 ); 749 );
488 750
489 /** 751 /**
496 * 758 *
497 * @param list the list 759 * @param list the list
498 * @param index the index where the iterator shall point at 760 * @param index the index where the iterator shall point at
499 * @return a new iterator 761 * @return a new iterator
500 */ 762 */
501 __attribute__((__nonnull__, __warn_unused_result__)) 763 cx_attr_nonnull
502 CxMutIterator cxListMutBackwardsIteratorAt( 764 cx_attr_nodiscard
765 cx_attr_export
766 CxIterator cxListMutBackwardsIteratorAt(
503 CxList *list, 767 CxList *list,
504 size_t index 768 size_t index
505 ); 769 );
506 770
507 /** 771 /**
512 * If the list is empty, a past-the-end iterator will be returned. 776 * If the list is empty, a past-the-end iterator will be returned.
513 * 777 *
514 * @param list the list 778 * @param list the list
515 * @return a new iterator 779 * @return a new iterator
516 */ 780 */
517 __attribute__((__nonnull__, __warn_unused_result__)) 781 cx_attr_nonnull
518 static inline CxIterator cxListIterator(CxList const *list) { 782 cx_attr_nodiscard
783 static inline CxIterator cxListIterator(const CxList *list) {
519 return list->cl->iterator(list, 0, false); 784 return list->cl->iterator(list, 0, false);
520 } 785 }
521 786
522 /** 787 /**
523 * Returns a mutating iterator pointing to the first item of the list. 788 * Returns a mutating iterator pointing to the first item of the list.
527 * If the list is empty, a past-the-end iterator will be returned. 792 * If the list is empty, a past-the-end iterator will be returned.
528 * 793 *
529 * @param list the list 794 * @param list the list
530 * @return a new iterator 795 * @return a new iterator
531 */ 796 */
532 __attribute__((__nonnull__, __warn_unused_result__)) 797 cx_attr_nonnull
533 static inline CxMutIterator cxListMutIterator(CxList *list) { 798 cx_attr_nodiscard
799 static inline CxIterator cxListMutIterator(CxList *list) {
534 return cxListMutIteratorAt(list, 0); 800 return cxListMutIteratorAt(list, 0);
535 } 801 }
536 802
537 803
538 /** 804 /**
543 * If the list is empty, a past-the-end iterator will be returned. 809 * If the list is empty, a past-the-end iterator will be returned.
544 * 810 *
545 * @param list the list 811 * @param list the list
546 * @return a new iterator 812 * @return a new iterator
547 */ 813 */
548 __attribute__((__nonnull__, __warn_unused_result__)) 814 cx_attr_nonnull
549 static inline CxIterator cxListBackwardsIterator(CxList const *list) { 815 cx_attr_nodiscard
550 return list->cl->iterator(list, list->size - 1, true); 816 static inline CxIterator cxListBackwardsIterator(const CxList *list) {
817 return list->cl->iterator(list, list->collection.size - 1, true);
551 } 818 }
552 819
553 /** 820 /**
554 * Returns a mutating backwards iterator pointing to the last item of the list. 821 * Returns a mutating backwards iterator pointing to the last item of the list.
555 * 822 *
558 * If the list is empty, a past-the-end iterator will be returned. 825 * If the list is empty, a past-the-end iterator will be returned.
559 * 826 *
560 * @param list the list 827 * @param list the list
561 * @return a new iterator 828 * @return a new iterator
562 */ 829 */
563 __attribute__((__nonnull__, __warn_unused_result__)) 830 cx_attr_nonnull
564 static inline CxMutIterator cxListMutBackwardsIterator(CxList *list) { 831 cx_attr_nodiscard
565 return cxListMutBackwardsIteratorAt(list, list->size - 1); 832 static inline CxIterator cxListMutBackwardsIterator(CxList *list) {
566 } 833 return cxListMutBackwardsIteratorAt(list, list->collection.size - 1);
567 834 }
568 /** 835
569 * Returns the index of the first element that equals \p elem. 836 /**
837 * Returns the index of the first element that equals @p elem.
570 * 838 *
571 * Determining equality is performed by the list's comparator function. 839 * Determining equality is performed by the list's comparator function.
572 * 840 *
573 * @param list the list 841 * @param list the list
574 * @param elem the element to find 842 * @param elem the element to find
575 * @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
576 * value when the element is not found 844 * @see cxListIndexValid()
577 */ 845 */
578 __attribute__((__nonnull__)) 846 cx_attr_nonnull
579 static inline ssize_t cxListFind( 847 cx_attr_nodiscard
580 CxList const *list, 848 static inline size_t cxListFind(
581 void const *elem 849 const CxList *list,
582 ) { 850 const void *elem
583 return list->cl->find(list, elem); 851 ) {
584 } 852 return list->cl->find_remove((CxList*)list, elem, false);
585 853 }
586 /** 854
587 * Sorts the list in-place. 855 /**
588 * 856 * Checks if the specified index is within bounds.
589 * \remark The underlying sort algorithm is implementation defined. 857 *
590 * 858 * @param list the list
591 * @param list the list 859 * @param index the index
592 */ 860 * @retval true if the index is within bounds
593 __attribute__((__nonnull__)) 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.
871 *
872 * Determining equality is performed by the list's comparator function.
873 *
874 * @param list the list
875 * @param elem the element to find and remove
876 * @return the index of the now removed element or the list size
877 * when the element is not found or could not be removed
878 * @see cxListIndexValid()
879 */
880 cx_attr_nonnull
881 static inline size_t cxListFindRemove(
882 CxList *list,
883 const void *elem
884 ) {
885 return list->cl->find_remove(list, elem, true);
886 }
887
888 /**
889 * Sorts the list.
890 *
891 * @remark The underlying sort algorithm is implementation defined.
892 *
893 * @param list the list
894 */
895 cx_attr_nonnull
594 static inline void cxListSort(CxList *list) { 896 static inline void cxListSort(CxList *list) {
595 list->cl->sort(list); 897 list->cl->sort(list);
898 list->collection.sorted = true;
596 } 899 }
597 900
598 /** 901 /**
599 * Reverses the order of the items. 902 * Reverses the order of the items.
600 * 903 *
601 * @param list the list 904 * @param list the list
602 */ 905 */
603 __attribute__((__nonnull__)) 906 cx_attr_nonnull
604 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;
605 list->cl->reverse(list); 910 list->cl->reverse(list);
606 } 911 }
607 912
608 /** 913 /**
609 * Compares a list to another list of the same type. 914 * Compares a list to another list of the same type.
611 * First, the list sizes are compared. 916 * First, the list sizes are compared.
612 * If they match, the lists are compared element-wise. 917 * If they match, the lists are compared element-wise.
613 * 918 *
614 * @param list the list 919 * @param list the list
615 * @param other the list to compare to 920 * @param other the list to compare to
616 * @return zero, if both lists are equal element wise, 921 * @retval zero both lists are equal element wise
617 * negative if the first list is smaller, positive if the first list is larger 922 * @retval negative the first list is smaller
618 */ 923 * or the first non-equal element in the first list is smaller
619 __attribute__((__nonnull__)) 924 * @retval positive the first list is larger
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
620 int cxListCompare( 930 int cxListCompare(
621 CxList const *list, 931 const CxList *list,
622 CxList const *other 932 const CxList *other
623 ); 933 );
624 934
625 /** 935 /**
626 * Deallocates the memory of the specified list structure. 936 * Deallocates the memory of the specified list structure.
627 * 937 *
628 * Also calls content a destructor function, depending on the configuration 938 * Also calls the content destructor functions for each element, if specified.
629 * in CxList.content_destructor_type. 939 *
630 * 940 * @param list the list which shall be freed
631 * This function itself is a destructor function for the CxList. 941 */
632 * 942 cx_attr_export
633 * @param list the list which shall be destroyed 943 void cxListFree(CxList *list);
634 */
635 __attribute__((__nonnull__))
636 void cxListDestroy(CxList *list);
637 944
638 /** 945 /**
639 * A shared instance of an empty list. 946 * A shared instance of an empty list.
640 * 947 *
641 * Writing to that list is undefined. 948 * Writing to that list is not allowed.
642 */ 949 *
643 extern CxList * const cxEmptyList; 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
954 extern CxList *const cxEmptyList;
644 955
645 956
646 #ifdef __cplusplus 957 #ifdef __cplusplus
647 } // extern "C" 958 } // extern "C"
648 #endif 959 #endif

mercurial