| 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 /** |
| |
56 * Common members for collections. |
| |
57 */ |
| 55 CX_COLLECTION_BASE; |
58 CX_COLLECTION_BASE; |
| 56 /** |
59 /** |
| 57 * The list class definition. |
60 * The list class definition. |
| 58 */ |
61 */ |
| 59 cx_list_class const *cl; |
62 const cx_list_class *cl; |
| 60 /** |
63 /** |
| 61 * The actual implementation in case the list class is delegating. |
64 * The actual implementation in case the list class is delegating. |
| 62 */ |
65 */ |
| 63 cx_list_class const *climpl; |
66 const cx_list_class *climpl; |
| 64 }; |
67 }; |
| 65 |
68 |
| 66 /** |
69 /** |
| 67 * The class definition for arbitrary lists. |
70 * The class definition for arbitrary lists. |
| 68 */ |
71 */ |
| 69 struct cx_list_class_s { |
72 struct cx_list_class_s { |
| 70 /** |
73 /** |
| 71 * Destructor function. |
74 * Destructor function. |
| 72 * |
75 * |
| 73 * Implementations SHALL invoke the content destructor functions if provided |
76 * Implementations SHALL invoke the content destructor functions if provided |
| 74 * and SHALL deallocate the list memory, if an allocator is provided. |
77 * and SHALL deallocate the entire list memory. |
| 75 */ |
78 */ |
| 76 void (*destructor)(struct cx_list_s *list); |
79 cx_attr_nonnull |
| |
80 void (*deallocate)(struct cx_list_s *list); |
| 77 |
81 |
| 78 /** |
82 /** |
| 79 * Member function for inserting a single element. |
83 * Member function for inserting a single element. |
| 80 * Implementors SHOULD see to performant implementations for corner cases. |
84 * Implementors SHOULD see to performant implementations for corner cases. |
| 81 */ |
85 */ |
| |
86 cx_attr_nonnull |
| 82 int (*insert_element)( |
87 int (*insert_element)( |
| 83 struct cx_list_s *list, |
88 struct cx_list_s *list, |
| 84 size_t index, |
89 size_t index, |
| 85 void const *data |
90 const void *data |
| 86 ); |
91 ); |
| 87 |
92 |
| 88 /** |
93 /** |
| 89 * Member function for inserting multiple elements. |
94 * Member function for inserting multiple elements. |
| 90 * Implementors SHOULD see to performant implementations for corner cases. |
95 * Implementors SHOULD see to performant implementations for corner cases. |
| 91 */ |
96 * @see cx_list_default_insert_array() |
| |
97 */ |
| |
98 cx_attr_nonnull |
| 92 size_t (*insert_array)( |
99 size_t (*insert_array)( |
| 93 struct cx_list_s *list, |
100 struct cx_list_s *list, |
| 94 size_t index, |
101 size_t index, |
| 95 void const *data, |
102 const void *data, |
| 96 size_t n |
103 size_t n |
| 97 ); |
104 ); |
| 98 |
105 |
| 99 /** |
106 /** |
| |
107 * Member function for inserting sorted elements into a sorted list. |
| |
108 * |
| |
109 * @see cx_list_default_insert_sorted() |
| |
110 */ |
| |
111 cx_attr_nonnull |
| |
112 size_t (*insert_sorted)( |
| |
113 struct cx_list_s *list, |
| |
114 const void *sorted_data, |
| |
115 size_t n |
| |
116 ); |
| |
117 |
| |
118 /** |
| 100 * Member function for inserting an element relative to an iterator position. |
119 * Member function for inserting an element relative to an iterator position. |
| 101 */ |
120 */ |
| |
121 cx_attr_nonnull |
| 102 int (*insert_iter)( |
122 int (*insert_iter)( |
| 103 struct cx_iterator_s *iter, |
123 struct cx_iterator_s *iter, |
| 104 void const *elem, |
124 const void *elem, |
| 105 int prepend |
125 int prepend |
| 106 ); |
126 ); |
| 107 |
127 |
| 108 /** |
128 /** |
| 109 * Member function for removing an element. |
129 * Member function for removing elements. |
| 110 */ |
130 * |
| 111 int (*remove)( |
131 * Implementations SHALL check if \p targetbuf is set and copy the elements |
| |
132 * to the buffer without invoking any destructor. |
| |
133 * When \p targetbuf is not set, the destructors SHALL be invoked. |
| |
134 * |
| |
135 * The function SHALL return the actual number of elements removed, which |
| |
136 * might be lower than \p num when going out of bounds. |
| |
137 */ |
| |
138 cx_attr_nonnull_arg(1) |
| |
139 cx_attr_access_w(4) |
| |
140 size_t (*remove)( |
| 112 struct cx_list_s *list, |
141 struct cx_list_s *list, |
| 113 size_t index |
142 size_t index, |
| |
143 size_t num, |
| |
144 void *targetbuf |
| 114 ); |
145 ); |
| 115 |
146 |
| 116 /** |
147 /** |
| 117 * Member function for removing all elements. |
148 * Member function for removing all elements. |
| 118 */ |
149 */ |
| |
150 cx_attr_nonnull |
| 119 void (*clear)(struct cx_list_s *list); |
151 void (*clear)(struct cx_list_s *list); |
| 120 |
152 |
| 121 /** |
153 /** |
| 122 * Member function for swapping two elements. |
154 * Member function for swapping two elements. |
| 123 */ |
155 * @see cx_list_default_swap() |
| |
156 */ |
| |
157 cx_attr_nonnull |
| 124 int (*swap)( |
158 int (*swap)( |
| 125 struct cx_list_s *list, |
159 struct cx_list_s *list, |
| 126 size_t i, |
160 size_t i, |
| 127 size_t j |
161 size_t j |
| 128 ); |
162 ); |
| 129 |
163 |
| 130 /** |
164 /** |
| 131 * Member function for element lookup. |
165 * Member function for element lookup. |
| 132 */ |
166 */ |
| |
167 cx_attr_nonnull |
| |
168 cx_attr_nodiscard |
| 133 void *(*at)( |
169 void *(*at)( |
| 134 struct cx_list_s const *list, |
170 const struct cx_list_s *list, |
| 135 size_t index |
171 size_t index |
| 136 ); |
172 ); |
| 137 |
173 |
| 138 /** |
174 /** |
| 139 * Member function for finding and optionally removing an element. |
175 * Member function for finding and optionally removing an element. |
| 140 */ |
176 */ |
| |
177 cx_attr_nonnull |
| |
178 cx_attr_nodiscard |
| 141 ssize_t (*find_remove)( |
179 ssize_t (*find_remove)( |
| 142 struct cx_list_s *list, |
180 struct cx_list_s *list, |
| 143 void const *elem, |
181 const void *elem, |
| 144 bool remove |
182 bool remove |
| 145 ); |
183 ); |
| 146 |
184 |
| 147 /** |
185 /** |
| 148 * Member function for sorting the list in-place. |
186 * Member function for sorting the list in-place. |
| 149 */ |
187 * @see cx_list_default_sort() |
| |
188 */ |
| |
189 cx_attr_nonnull |
| 150 void (*sort)(struct cx_list_s *list); |
190 void (*sort)(struct cx_list_s *list); |
| 151 |
191 |
| 152 /** |
192 /** |
| 153 * Member function for comparing this list to another list of the same type. |
193 * Optional member function for comparing this list |
| 154 */ |
194 * to another list of the same type. |
| |
195 * If set to \c NULL, comparison won't be optimized. |
| |
196 */ |
| |
197 cx_attr_nonnull |
| 155 int (*compare)( |
198 int (*compare)( |
| 156 struct cx_list_s const *list, |
199 const struct cx_list_s *list, |
| 157 struct cx_list_s const *other |
200 const struct cx_list_s *other |
| 158 ); |
201 ); |
| 159 |
202 |
| 160 /** |
203 /** |
| 161 * Member function for reversing the order of the items. |
204 * Member function for reversing the order of the items. |
| 162 */ |
205 */ |
| |
206 cx_attr_nonnull |
| 163 void (*reverse)(struct cx_list_s *list); |
207 void (*reverse)(struct cx_list_s *list); |
| 164 |
208 |
| 165 /** |
209 /** |
| 166 * Member function for returning an iterator pointing to the specified index. |
210 * Member function for returning an iterator pointing to the specified index. |
| 167 */ |
211 */ |
| |
212 cx_attr_nonnull |
| 168 struct cx_iterator_s (*iterator)( |
213 struct cx_iterator_s (*iterator)( |
| 169 struct cx_list_s const *list, |
214 const struct cx_list_s *list, |
| 170 size_t index, |
215 size_t index, |
| 171 bool backward |
216 bool backward |
| 172 ); |
217 ); |
| 173 }; |
218 }; |
| 174 |
219 |
| 175 /** |
220 /** |
| |
221 * Default implementation of an array insert. |
| |
222 * |
| |
223 * This function uses the element insert function for each element of the array. |
| |
224 * |
| |
225 * Use this in your own list class if you do not want to implement an optimized |
| |
226 * version for your list. |
| |
227 * |
| |
228 * @param list the list |
| |
229 * @param index the index where to insert the data |
| |
230 * @param data a pointer to the array of data to insert |
| |
231 * @param n the number of elements to insert |
| |
232 * @return the number of elements actually inserted |
| |
233 */ |
| |
234 cx_attr_nonnull |
| |
235 size_t cx_list_default_insert_array( |
| |
236 struct cx_list_s *list, |
| |
237 size_t index, |
| |
238 const void *data, |
| |
239 size_t n |
| |
240 ); |
| |
241 |
| |
242 /** |
| |
243 * Default implementation of a sorted insert. |
| |
244 * |
| |
245 * This function uses the array insert function to insert consecutive groups |
| |
246 * of sorted data. |
| |
247 * |
| |
248 * The source data \em must already be sorted wrt. the list's compare function. |
| |
249 * |
| |
250 * Use this in your own list class if you do not want to implement an optimized |
| |
251 * version for your list. |
| |
252 * |
| |
253 * @param list the list |
| |
254 * @param sorted_data a pointer to the array of pre-sorted data to insert |
| |
255 * @param n the number of elements to insert |
| |
256 * @return the number of elements actually inserted |
| |
257 */ |
| |
258 cx_attr_nonnull |
| |
259 size_t cx_list_default_insert_sorted( |
| |
260 struct cx_list_s *list, |
| |
261 const void *sorted_data, |
| |
262 size_t n |
| |
263 ); |
| |
264 |
| |
265 /** |
| |
266 * Default unoptimized sort implementation. |
| |
267 * |
| |
268 * This function will copy all data to an array, sort the array with standard |
| |
269 * qsort, and then copy the data back to the list memory. |
| |
270 * |
| |
271 * Use this in your own list class if you do not want to implement an optimized |
| |
272 * version for your list. |
| |
273 * |
| |
274 * @param list the list that shall be sorted |
| |
275 */ |
| |
276 cx_attr_nonnull |
| |
277 void cx_list_default_sort(struct cx_list_s *list); |
| |
278 |
| |
279 /** |
| |
280 * Default unoptimized swap implementation. |
| |
281 * |
| |
282 * Use this in your own list class if you do not want to implement an optimized |
| |
283 * version for your list. |
| |
284 * |
| |
285 * @param list the list in which to swap |
| |
286 * @param i index of one element |
| |
287 * @param j index of the other element |
| |
288 * @return zero on success, non-zero when indices are out of bounds or memory |
| |
289 * allocation for the temporary buffer fails |
| |
290 */ |
| |
291 cx_attr_nonnull |
| |
292 int cx_list_default_swap(struct cx_list_s *list, size_t i, size_t j); |
| |
293 |
| |
294 /** |
| 176 * Common type for all list implementations. |
295 * Common type for all list implementations. |
| 177 */ |
296 */ |
| 178 typedef struct cx_list_s CxList; |
297 typedef struct cx_list_s CxList; |
| 179 |
298 |
| 180 /** |
299 /** |
| 199 * objects is undefined. |
318 * objects is undefined. |
| 200 * |
319 * |
| 201 * @param list the list |
320 * @param list the list |
| 202 * @see cxListStoreObjects() |
321 * @see cxListStoreObjects() |
| 203 */ |
322 */ |
| 204 __attribute__((__nonnull__)) |
323 cx_attr_nonnull |
| 205 void cxListStorePointers(CxList *list); |
324 void cxListStorePointers(CxList *list); |
| 206 |
325 |
| 207 /** |
326 /** |
| 208 * Returns true, if this list is storing pointers instead of the actual data. |
327 * Returns true, if this list is storing pointers instead of the actual data. |
| 209 * |
328 * |
| 210 * @param list |
329 * @param list |
| 211 * @return true, if this list is storing pointers |
330 * @return true, if this list is storing pointers |
| 212 * @see cxListStorePointers() |
331 * @see cxListStorePointers() |
| 213 */ |
332 */ |
| 214 __attribute__((__nonnull__)) |
333 cx_attr_nonnull |
| 215 static inline bool cxListIsStoringPointers(CxList const *list) { |
334 static inline bool cxListIsStoringPointers(const CxList *list) { |
| 216 return list->collection.store_pointer; |
335 return list->collection.store_pointer; |
| 217 } |
336 } |
| 218 |
337 |
| 219 /** |
338 /** |
| 220 * Returns the number of elements currently stored in the list. |
339 * Returns the number of elements currently stored in the list. |
| 221 * |
340 * |
| 222 * @param list the list |
341 * @param list the list |
| 223 * @return the number of currently stored elements |
342 * @return the number of currently stored elements |
| 224 */ |
343 */ |
| 225 __attribute__((__nonnull__)) |
344 cx_attr_nonnull |
| 226 static inline size_t cxListSize(CxList const *list) { |
345 static inline size_t cxListSize(const CxList *list) { |
| 227 return list->collection.size; |
346 return list->collection.size; |
| 228 } |
347 } |
| 229 |
348 |
| 230 /** |
349 /** |
| 231 * Adds an item to the end of the list. |
350 * Adds an item to the end of the list. |
| 307 * @param index the index where to add the elements |
442 * @param index the index where to add the elements |
| 308 * @param array a pointer to the elements to add |
443 * @param array a pointer to the elements to add |
| 309 * @param n the number of elements to add |
444 * @param n the number of elements to add |
| 310 * @return the number of added elements |
445 * @return the number of added elements |
| 311 */ |
446 */ |
| 312 __attribute__((__nonnull__)) |
447 cx_attr_nonnull |
| 313 static inline size_t cxListInsertArray( |
448 static inline size_t cxListInsertArray( |
| 314 CxList *list, |
449 CxList *list, |
| 315 size_t index, |
450 size_t index, |
| 316 void const *array, |
451 const void *array, |
| 317 size_t n |
452 size_t n |
| 318 ) { |
453 ) { |
| 319 return list->cl->insert_array(list, index, array, n); |
454 return list->cl->insert_array(list, index, array, n); |
| |
455 } |
| |
456 |
| |
457 /** |
| |
458 * Inserts a sorted array into a sorted list. |
| |
459 * |
| |
460 * This method is usually more efficient than inserting each element separately, |
| |
461 * because consecutive chunks of sorted data are inserted in one pass. |
| |
462 * |
| |
463 * If there is not enough memory to add all elements, the returned value is |
| |
464 * less than \p n. |
| |
465 * |
| |
466 * If this list is storing pointers instead of objects \p array is expected to |
| |
467 * be an array of pointers. |
| |
468 * |
| |
469 * @param list the list |
| |
470 * @param array a pointer to the elements to add |
| |
471 * @param n the number of elements to add |
| |
472 * @return the number of added elements |
| |
473 */ |
| |
474 cx_attr_nonnull |
| |
475 static inline size_t cxListInsertSortedArray( |
| |
476 CxList *list, |
| |
477 const void *array, |
| |
478 size_t n |
| |
479 ) { |
| |
480 return list->cl->insert_sorted(list, array, n); |
| 320 } |
481 } |
| 321 |
482 |
| 322 /** |
483 /** |
| 323 * Inserts an element after the current location of the specified iterator. |
484 * Inserts an element after the current location of the specified iterator. |
| 324 * |
485 * |
| 373 * |
534 * |
| 374 * @param list the list |
535 * @param list the list |
| 375 * @param index the index of the element |
536 * @param index the index of the element |
| 376 * @return zero on success, non-zero if the index is out of bounds |
537 * @return zero on success, non-zero if the index is out of bounds |
| 377 */ |
538 */ |
| 378 __attribute__((__nonnull__)) |
539 cx_attr_nonnull |
| 379 static inline int cxListRemove( |
540 static inline int cxListRemove( |
| 380 CxList *list, |
541 CxList *list, |
| 381 size_t index |
542 size_t index |
| 382 ) { |
543 ) { |
| 383 return list->cl->remove(list, index); |
544 return list->cl->remove(list, index, 1, NULL) == 0; |
| |
545 } |
| |
546 |
| |
547 /** |
| |
548 * Removes and returns the element at the specified index. |
| |
549 * |
| |
550 * 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. |
| |
552 * |
| |
553 * @param list the list |
| |
554 * @param index the index of the element |
| |
555 * @param targetbuf a buffer where to copy the element |
| |
556 * @return zero on success, non-zero if the index is out of bounds |
| |
557 */ |
| |
558 cx_attr_nonnull |
| |
559 cx_attr_access_w(3) |
| |
560 static inline int cxListRemoveAndGet( |
| |
561 CxList *list, |
| |
562 size_t index, |
| |
563 void *targetbuf |
| |
564 ) { |
| |
565 return list->cl->remove(list, index, 1, targetbuf) == 0; |
| |
566 } |
| |
567 |
| |
568 /** |
| |
569 * Removes multiple element starting at the specified index. |
| |
570 * |
| |
571 * If an element destructor function is specified, it is called for each |
| |
572 * element. It is guaranteed that the destructor is called before removing |
| |
573 * the element, however, due to possible optimizations it is neither guaranteed |
| |
574 * that the destructors are invoked for all elements before starting to remove |
| |
575 * them, nor that the element is removed immediately after the destructor call |
| |
576 * before proceeding to the next element. |
| |
577 * |
| |
578 * @param list the list |
| |
579 * @param index the index of the element |
| |
580 * @param num the number of elements to remove |
| |
581 * @return the actual number of removed elements |
| |
582 */ |
| |
583 cx_attr_nonnull |
| |
584 static inline size_t cxListRemoveArray( |
| |
585 CxList *list, |
| |
586 size_t index, |
| |
587 size_t num |
| |
588 ) { |
| |
589 return list->cl->remove(list, index, num, NULL); |
| |
590 } |
| |
591 |
| |
592 /** |
| |
593 * Removes and returns multiple element starting at the specified index. |
| |
594 * |
| |
595 * 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. |
| |
597 * |
| |
598 * @param list the list |
| |
599 * @param index the index of the element |
| |
600 * @param num the number of elements to remove |
| |
601 * @param targetbuf a buffer where to copy the elements |
| |
602 * @return the actual number of removed elements |
| |
603 */ |
| |
604 cx_attr_nonnull |
| |
605 cx_attr_access_w(4) |
| |
606 static inline size_t cxListRemoveArrayAndGet( |
| |
607 CxList *list, |
| |
608 size_t index, |
| |
609 size_t num, |
| |
610 void *targetbuf |
| |
611 ) { |
| |
612 return list->cl->remove(list, index, num, targetbuf); |
| 384 } |
613 } |
| 385 |
614 |
| 386 /** |
615 /** |
| 387 * Removes all elements from this list. |
616 * Removes all elements from this list. |
| 388 * |
617 * |
| 389 * If an element destructor function is specified, it is called for each |
618 * If an element destructor function is specified, it is called for each |
| 390 * element before removing them. |
619 * element before removing them. |
| 391 * |
620 * |
| 392 * @param list the list |
621 * @param list the list |
| 393 */ |
622 */ |
| 394 __attribute__((__nonnull__)) |
623 cx_attr_nonnull |
| 395 static inline void cxListClear(CxList *list) { |
624 static inline void cxListClear(CxList *list) { |
| 396 list->cl->clear(list); |
625 list->cl->clear(list); |
| 397 } |
626 } |
| 398 |
627 |
| 399 /** |
628 /** |