50 |
50 |
51 /** |
51 /** |
52 * Structure for holding the base data of a list. |
52 * Structure for holding the base data of a list. |
53 */ |
53 */ |
54 struct cx_list_s { |
54 struct cx_list_s { |
55 CX_COLLECTION_MEMBERS |
55 CX_COLLECTION_BASE; |
56 /** |
56 /** |
57 * The list class definition. |
57 * The list class definition. |
58 */ |
58 */ |
59 cx_list_class const *cl; |
59 const cx_list_class *cl; |
60 /** |
60 /** |
61 * The actual implementation in case the list class is delegating. |
61 * The actual implementation in case the list class is delegating. |
62 */ |
62 */ |
63 cx_list_class const *climpl; |
63 const cx_list_class *climpl; |
64 }; |
64 }; |
65 |
65 |
66 /** |
66 /** |
67 * The class definition for arbitrary lists. |
67 * The class definition for arbitrary lists. |
68 */ |
68 */ |
69 struct cx_list_class_s { |
69 struct cx_list_class_s { |
70 /** |
70 /** |
71 * Destructor function. |
71 * Destructor function. |
72 * |
72 * |
73 * Implementations SHALL invoke the content destructor functions if provided |
73 * Implementations SHALL invoke the content destructor functions if provided |
74 * and SHALL deallocate the list memory, if an allocator is provided. |
74 * and SHALL deallocate the list memory. |
75 */ |
75 */ |
76 void (*destructor)(struct cx_list_s *list); |
76 void (*destructor)(struct cx_list_s *list); |
77 |
77 |
78 /** |
78 /** |
79 * Member function for inserting a single element. |
79 * Member function for inserting a single element. |
80 * Implementors SHOULD see to performant implementations for corner cases. |
80 * Implementors SHOULD see to performant implementations for corner cases. |
81 */ |
81 */ |
82 int (*insert_element)( |
82 int (*insert_element)( |
83 struct cx_list_s *list, |
83 struct cx_list_s *list, |
84 size_t index, |
84 size_t index, |
85 void const *data |
85 const void *data |
86 ); |
86 ); |
87 |
87 |
88 /** |
88 /** |
89 * Member function for inserting multiple elements. |
89 * Member function for inserting multiple elements. |
90 * Implementors SHOULD see to performant implementations for corner cases. |
90 * Implementors SHOULD see to performant implementations for corner cases. |
|
91 * @see cx_list_default_insert_array() |
91 */ |
92 */ |
92 size_t (*insert_array)( |
93 size_t (*insert_array)( |
93 struct cx_list_s *list, |
94 struct cx_list_s *list, |
94 size_t index, |
95 size_t index, |
95 void const *data, |
96 const void *data, |
96 size_t n |
97 size_t n |
97 ); |
98 ); |
98 |
99 |
99 /** |
100 /** |
|
101 * Member function for inserting sorted elements into a sorted list. |
|
102 * |
|
103 * @see cx_list_default_insert_sorted() |
|
104 */ |
|
105 size_t (*insert_sorted)( |
|
106 struct cx_list_s *list, |
|
107 const void *sorted_data, |
|
108 size_t n |
|
109 ); |
|
110 |
|
111 /** |
100 * Member function for inserting an element relative to an iterator position. |
112 * Member function for inserting an element relative to an iterator position. |
101 */ |
113 */ |
102 int (*insert_iter)( |
114 int (*insert_iter)( |
103 struct cx_mut_iterator_s *iter, |
115 struct cx_iterator_s *iter, |
104 void const *elem, |
116 const void *elem, |
105 int prepend |
117 int prepend |
106 ); |
118 ); |
107 |
119 |
108 /** |
120 /** |
109 * Member function for removing an element. |
121 * Member function for removing an element. |
129 |
142 |
130 /** |
143 /** |
131 * Member function for element lookup. |
144 * Member function for element lookup. |
132 */ |
145 */ |
133 void *(*at)( |
146 void *(*at)( |
134 struct cx_list_s const *list, |
147 const struct cx_list_s *list, |
135 size_t index |
148 size_t index |
136 ); |
149 ); |
137 |
150 |
138 /** |
151 /** |
139 * Member function for finding and optionally removing an element. |
152 * Member function for finding and optionally removing an element. |
140 */ |
153 */ |
141 ssize_t (*find_remove)( |
154 ssize_t (*find_remove)( |
142 struct cx_list_s *list, |
155 struct cx_list_s *list, |
143 void const *elem, |
156 const void *elem, |
144 bool remove |
157 bool remove |
145 ); |
158 ); |
146 |
159 |
147 /** |
160 /** |
148 * Member function for sorting the list in-place. |
161 * Member function for sorting the list in-place. |
|
162 * @see cx_list_default_sort() |
149 */ |
163 */ |
150 void (*sort)(struct cx_list_s *list); |
164 void (*sort)(struct cx_list_s *list); |
151 |
165 |
152 /** |
166 /** |
153 * Member function for comparing this list to another list of the same type. |
167 * Optional member function for comparing this list |
|
168 * to another list of the same type. |
|
169 * If set to \c NULL, comparison won't be optimized. |
154 */ |
170 */ |
155 int (*compare)( |
171 int (*compare)( |
156 struct cx_list_s const *list, |
172 const struct cx_list_s *list, |
157 struct cx_list_s const *other |
173 const struct cx_list_s *other |
158 ); |
174 ); |
159 |
175 |
160 /** |
176 /** |
161 * Member function for reversing the order of the items. |
177 * Member function for reversing the order of the items. |
162 */ |
178 */ |
164 |
180 |
165 /** |
181 /** |
166 * Member function for returning an iterator pointing to the specified index. |
182 * Member function for returning an iterator pointing to the specified index. |
167 */ |
183 */ |
168 struct cx_iterator_s (*iterator)( |
184 struct cx_iterator_s (*iterator)( |
169 struct cx_list_s const *list, |
185 const struct cx_list_s *list, |
170 size_t index, |
186 size_t index, |
171 bool backward |
187 bool backward |
172 ); |
188 ); |
173 }; |
189 }; |
|
190 |
|
191 /** |
|
192 * Default implementation of an array insert. |
|
193 * |
|
194 * This function uses the element insert function for each element of the array. |
|
195 * |
|
196 * Use this in your own list class if you do not want to implement an optimized |
|
197 * version for your list. |
|
198 * |
|
199 * @param list the list |
|
200 * @param index the index where to insert the data |
|
201 * @param data a pointer to the array of data to insert |
|
202 * @param n the number of elements to insert |
|
203 * @return the number of elements actually inserted |
|
204 */ |
|
205 __attribute__((__nonnull__)) |
|
206 size_t cx_list_default_insert_array( |
|
207 struct cx_list_s *list, |
|
208 size_t index, |
|
209 const void *data, |
|
210 size_t n |
|
211 ); |
|
212 |
|
213 /** |
|
214 * Default implementation of a sorted insert. |
|
215 * |
|
216 * This function uses the array insert function to insert consecutive groups |
|
217 * of sorted data. |
|
218 * |
|
219 * The source data \em must already be sorted wrt. the list's compare function. |
|
220 * |
|
221 * Use this in your own list class if you do not want to implement an optimized |
|
222 * version for your list. |
|
223 * |
|
224 * @param list the list |
|
225 * @param sorted_data a pointer to the array of pre-sorted data to insert |
|
226 * @param n the number of elements to insert |
|
227 * @return the number of elements actually inserted |
|
228 */ |
|
229 __attribute__((__nonnull__)) |
|
230 size_t cx_list_default_insert_sorted( |
|
231 struct cx_list_s *list, |
|
232 const void *sorted_data, |
|
233 size_t n |
|
234 ); |
|
235 |
|
236 /** |
|
237 * Default unoptimized sort implementation. |
|
238 * |
|
239 * This function will copy all data to an array, sort the array with standard |
|
240 * qsort, and then copy the data back to the list memory. |
|
241 * |
|
242 * Use this in your own list class if you do not want to implement an optimized |
|
243 * version for your list. |
|
244 * |
|
245 * @param list the list that shall be sorted |
|
246 */ |
|
247 __attribute__((__nonnull__)) |
|
248 void cx_list_default_sort(struct cx_list_s *list); |
|
249 |
|
250 /** |
|
251 * Default unoptimized swap implementation. |
|
252 * |
|
253 * Use this in your own list class if you do not want to implement an optimized |
|
254 * version for your list. |
|
255 * |
|
256 * @param list the list in which to swap |
|
257 * @param i index of one element |
|
258 * @param j index of the other element |
|
259 * @return zero on success, non-zero when indices are out of bounds or memory |
|
260 * allocation for the temporary buffer fails |
|
261 */ |
|
262 __attribute__((__nonnull__)) |
|
263 int cx_list_default_swap(struct cx_list_s *list, size_t i, size_t j); |
174 |
264 |
175 /** |
265 /** |
176 * Common type for all list implementations. |
266 * Common type for all list implementations. |
177 */ |
267 */ |
178 typedef struct cx_list_s CxList; |
268 typedef struct cx_list_s CxList; |
210 * @param list |
300 * @param list |
211 * @return true, if this list is storing pointers |
301 * @return true, if this list is storing pointers |
212 * @see cxListStorePointers() |
302 * @see cxListStorePointers() |
213 */ |
303 */ |
214 __attribute__((__nonnull__)) |
304 __attribute__((__nonnull__)) |
215 static inline bool cxListIsStoringPointers(CxList const *list) { |
305 static inline bool cxListIsStoringPointers(const CxList *list) { |
216 return list->store_pointer; |
306 return list->collection.store_pointer; |
217 } |
307 } |
218 |
308 |
219 /** |
309 /** |
220 * Returns the number of elements currently stored in the list. |
310 * Returns the number of elements currently stored in the list. |
221 * |
311 * |
222 * @param list the list |
312 * @param list the list |
223 * @return the number of currently stored elements |
313 * @return the number of currently stored elements |
224 */ |
314 */ |
225 __attribute__((__nonnull__)) |
315 __attribute__((__nonnull__)) |
226 static inline size_t cxListSize(CxList const *list) { |
316 static inline size_t cxListSize(const CxList *list) { |
227 return list->size; |
317 return list->collection.size; |
228 } |
318 } |
229 |
319 |
230 /** |
320 /** |
231 * Adds an item to the end of the list. |
321 * Adds an item to the end of the list. |
232 * |
322 * |
260 * @return the number of added elements |
350 * @return the number of added elements |
261 */ |
351 */ |
262 __attribute__((__nonnull__)) |
352 __attribute__((__nonnull__)) |
263 static inline size_t cxListAddArray( |
353 static inline size_t cxListAddArray( |
264 CxList *list, |
354 CxList *list, |
265 void const *array, |
355 const void *array, |
266 size_t n |
356 size_t n |
267 ) { |
357 ) { |
268 return list->cl->insert_array(list, list->size, array, n); |
358 return list->cl->insert_array(list, list->collection.size, array, n); |
269 } |
359 } |
270 |
360 |
271 /** |
361 /** |
272 * Inserts an item at the specified index. |
362 * Inserts an item at the specified index. |
273 * |
363 * |
283 */ |
373 */ |
284 __attribute__((__nonnull__)) |
374 __attribute__((__nonnull__)) |
285 static inline int cxListInsert( |
375 static inline int cxListInsert( |
286 CxList *list, |
376 CxList *list, |
287 size_t index, |
377 size_t index, |
288 void const *elem |
378 const void *elem |
289 ) { |
379 ) { |
290 return list->cl->insert_element(list, index, elem); |
380 return list->cl->insert_element(list, index, elem); |
|
381 } |
|
382 |
|
383 /** |
|
384 * Inserts an item into a sorted list. |
|
385 * |
|
386 * @param list the list |
|
387 * @param elem a pointer to the element to add |
|
388 * @return zero on success, non-zero on memory allocation failure |
|
389 */ |
|
390 __attribute__((__nonnull__)) |
|
391 static inline int cxListInsertSorted( |
|
392 CxList *list, |
|
393 const void *elem |
|
394 ) { |
|
395 const void *data = list->collection.store_pointer ? &elem : elem; |
|
396 return list->cl->insert_sorted(list, data, 1) == 0; |
291 } |
397 } |
292 |
398 |
293 /** |
399 /** |
294 * Inserts multiple items to the list at the specified index. |
400 * Inserts multiple items to the list at the specified index. |
295 * If \p index equals the list size, this is effectively cxListAddArray(). |
401 * If \p index equals the list size, this is effectively cxListAddArray(). |
311 */ |
417 */ |
312 __attribute__((__nonnull__)) |
418 __attribute__((__nonnull__)) |
313 static inline size_t cxListInsertArray( |
419 static inline size_t cxListInsertArray( |
314 CxList *list, |
420 CxList *list, |
315 size_t index, |
421 size_t index, |
316 void const *array, |
422 const void *array, |
317 size_t n |
423 size_t n |
318 ) { |
424 ) { |
319 return list->cl->insert_array(list, index, array, n); |
425 return list->cl->insert_array(list, index, array, n); |
|
426 } |
|
427 |
|
428 /** |
|
429 * Inserts a sorted array into a sorted list. |
|
430 * |
|
431 * This method is usually more efficient than inserting each element separately, |
|
432 * because consecutive chunks of sorted data are inserted in one pass. |
|
433 * |
|
434 * If there is not enough memory to add all elements, the returned value is |
|
435 * less than \p n. |
|
436 * |
|
437 * If this list is storing pointers instead of objects \p array is expected to |
|
438 * be an array of pointers. |
|
439 * |
|
440 * @param list the list |
|
441 * @param array a pointer to the elements to add |
|
442 * @param n the number of elements to add |
|
443 * @return the number of added elements |
|
444 */ |
|
445 __attribute__((__nonnull__)) |
|
446 static inline size_t cxListInsertSortedArray( |
|
447 CxList *list, |
|
448 const void *array, |
|
449 size_t n |
|
450 ) { |
|
451 return list->cl->insert_sorted(list, array, n); |
320 } |
452 } |
321 |
453 |
322 /** |
454 /** |
323 * Inserts an element after the current location of the specified iterator. |
455 * Inserts an element after the current location of the specified iterator. |
324 * |
456 * |
334 * @see cxListInsert() |
466 * @see cxListInsert() |
335 * @see cxListInsertBefore() |
467 * @see cxListInsertBefore() |
336 */ |
468 */ |
337 __attribute__((__nonnull__)) |
469 __attribute__((__nonnull__)) |
338 static inline int cxListInsertAfter( |
470 static inline int cxListInsertAfter( |
339 CxMutIterator *iter, |
471 CxIterator *iter, |
340 void const *elem |
472 const void *elem |
341 ) { |
473 ) { |
342 return ((struct cx_list_s *) iter->src_handle)->cl->insert_iter(iter, elem, 0); |
474 return ((struct cx_list_s *) iter->src_handle.m)->cl->insert_iter(iter, elem, 0); |
343 } |
475 } |
344 |
476 |
345 /** |
477 /** |
346 * Inserts an element before the current location of the specified iterator. |
478 * Inserts an element before the current location of the specified iterator. |
347 * |
479 * |
357 * @see cxListInsert() |
489 * @see cxListInsert() |
358 * @see cxListInsertAfter() |
490 * @see cxListInsertAfter() |
359 */ |
491 */ |
360 __attribute__((__nonnull__)) |
492 __attribute__((__nonnull__)) |
361 static inline int cxListInsertBefore( |
493 static inline int cxListInsertBefore( |
362 CxMutIterator *iter, |
494 CxIterator *iter, |
363 void const *elem |
495 const void *elem |
364 ) { |
496 ) { |
365 return ((struct cx_list_s *) iter->src_handle)->cl->insert_iter(iter, elem, 1); |
497 return ((struct cx_list_s *) iter->src_handle.m)->cl->insert_iter(iter, elem, 1); |
366 } |
498 } |
367 |
499 |
368 /** |
500 /** |
369 * Removes the element at the specified index. |
501 * Removes the element at the specified index. |
370 * |
502 * |
442 * @param index the index where the iterator shall point at |
574 * @param index the index where the iterator shall point at |
443 * @return a new iterator |
575 * @return a new iterator |
444 */ |
576 */ |
445 __attribute__((__nonnull__, __warn_unused_result__)) |
577 __attribute__((__nonnull__, __warn_unused_result__)) |
446 static inline CxIterator cxListIteratorAt( |
578 static inline CxIterator cxListIteratorAt( |
447 CxList const *list, |
579 const CxList *list, |
448 size_t index |
580 size_t index |
449 ) { |
581 ) { |
450 return list->cl->iterator(list, index, false); |
582 return list->cl->iterator(list, index, false); |
451 } |
583 } |
452 |
584 |
461 * @param index the index where the iterator shall point at |
593 * @param index the index where the iterator shall point at |
462 * @return a new iterator |
594 * @return a new iterator |
463 */ |
595 */ |
464 __attribute__((__nonnull__, __warn_unused_result__)) |
596 __attribute__((__nonnull__, __warn_unused_result__)) |
465 static inline CxIterator cxListBackwardsIteratorAt( |
597 static inline CxIterator cxListBackwardsIteratorAt( |
466 CxList const *list, |
598 const CxList *list, |
467 size_t index |
599 size_t index |
468 ) { |
600 ) { |
469 return list->cl->iterator(list, index, true); |
601 return list->cl->iterator(list, index, true); |
470 } |
602 } |
471 |
603 |
513 * |
645 * |
514 * @param list the list |
646 * @param list the list |
515 * @return a new iterator |
647 * @return a new iterator |
516 */ |
648 */ |
517 __attribute__((__nonnull__, __warn_unused_result__)) |
649 __attribute__((__nonnull__, __warn_unused_result__)) |
518 static inline CxIterator cxListIterator(CxList const *list) { |
650 static inline CxIterator cxListIterator(const CxList *list) { |
519 return list->cl->iterator(list, 0, false); |
651 return list->cl->iterator(list, 0, false); |
520 } |
652 } |
521 |
653 |
522 /** |
654 /** |
523 * Returns a mutating iterator pointing to the first item of the list. |
655 * Returns a mutating iterator pointing to the first item of the list. |
544 * |
676 * |
545 * @param list the list |
677 * @param list the list |
546 * @return a new iterator |
678 * @return a new iterator |
547 */ |
679 */ |
548 __attribute__((__nonnull__, __warn_unused_result__)) |
680 __attribute__((__nonnull__, __warn_unused_result__)) |
549 static inline CxIterator cxListBackwardsIterator(CxList const *list) { |
681 static inline CxIterator cxListBackwardsIterator(const CxList *list) { |
550 return list->cl->iterator(list, list->size - 1, true); |
682 return list->cl->iterator(list, list->collection.size - 1, true); |
551 } |
683 } |
552 |
684 |
553 /** |
685 /** |
554 * Returns a mutating backwards iterator pointing to the last item of the list. |
686 * Returns a mutating backwards iterator pointing to the last item of the list. |
555 * |
687 * |
559 * |
691 * |
560 * @param list the list |
692 * @param list the list |
561 * @return a new iterator |
693 * @return a new iterator |
562 */ |
694 */ |
563 __attribute__((__nonnull__, __warn_unused_result__)) |
695 __attribute__((__nonnull__, __warn_unused_result__)) |
564 static inline CxMutIterator cxListMutBackwardsIterator(CxList *list) { |
696 static inline CxIterator cxListMutBackwardsIterator(CxList *list) { |
565 return cxListMutBackwardsIteratorAt(list, list->size - 1); |
697 return cxListMutBackwardsIteratorAt(list, list->collection.size - 1); |
566 } |
698 } |
567 |
699 |
568 /** |
700 /** |
569 * Returns the index of the first element that equals \p elem. |
701 * Returns the index of the first element that equals \p elem. |
570 * |
702 * |