ucx/cx/list.h

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

mercurial