src/ucx/cx/list.h

changeset 490
d218607f5a7e
parent 438
22eca559aded
child 504
c094afcdfb27
equal deleted inserted replaced
489:921f83a8943f 490:d218607f5a7e
36 36
37 #ifndef UCX_LIST_H 37 #ifndef UCX_LIST_H
38 #define UCX_LIST_H 38 #define UCX_LIST_H
39 39
40 #include "common.h" 40 #include "common.h"
41 #include "allocator.h" 41 #include "collection.h"
42 #include "iterator.h"
43 42
44 #ifdef __cplusplus 43 #ifdef __cplusplus
45 extern "C" { 44 extern "C" {
46 #endif 45 #endif
47 46
48 /** 47 /**
49 * A comparator function comparing two list elements.
50 */
51 typedef int(*CxListComparator)(
52 void const *left,
53 void const *right
54 );
55
56 /**
57 * List class type. 48 * List class type.
58 */ 49 */
59 typedef struct cx_list_class_s cx_list_class; 50 typedef struct cx_list_class_s cx_list_class;
60 51
61 /** 52 /**
62 * Structure for holding the base data of a list. 53 * Structure for holding the base data of a list.
63 */ 54 */
64 struct cx_list_s { 55 struct cx_list_s {
56 CX_COLLECTION_MEMBERS
65 /** 57 /**
66 * The list class definition. 58 * The list class definition.
67 */ 59 */
68 cx_list_class *cl; 60 cx_list_class const *cl;
69 /** 61 /**
70 * The allocator to use. 62 * The actual implementation in case the list class is delegating.
71 */ 63 */
72 CxAllocator const *allocator; 64 cx_list_class const *climpl;
73 /**
74 * The comparator function for the elements.
75 */
76 CxListComparator cmpfunc;
77 /**
78 * The size of each element (payload only).
79 */
80 size_t itemsize;
81 /**
82 * The size of the list (number of currently stored elements).
83 */
84 size_t size;
85 /**
86 * The capacity of the list (maximum number of elements).
87 */
88 size_t capacity;
89 union {
90 /**
91 * An optional simple destructor for the list contents that admits the free() interface.
92 *
93 * @remark Set content_destructor_type to #CX_DESTRUCTOR_SIMPLE.
94 *
95 * @attention Read the documentation of the particular list implementation
96 * whether this destructor shall only destroy the contents or also free the memory.
97 */
98 cx_destructor_func simple_destructor;
99 /**
100 * An optional advanced destructor for the list contents providing additional data.
101 *
102 * @remark Set content_destructor_type to #CX_DESTRUCTOR_ADVANCED.
103 *
104 * @attention Read the documentation of the particular list implementation
105 * whether this destructor shall only destroy the contents or also free the memory.
106 */
107 cx_advanced_destructor advanced_destructor;
108 };
109 /**
110 * The type of destructor to use.
111 */
112 enum cx_destructor_type content_destructor_type;
113 }; 65 };
114 66
115 /** 67 /**
116 * The class definition for arbitrary lists. 68 * The class definition for arbitrary lists.
117 */ 69 */
120 * Destructor function. 72 * Destructor function.
121 */ 73 */
122 void (*destructor)(struct cx_list_s *list); 74 void (*destructor)(struct cx_list_s *list);
123 75
124 /** 76 /**
125 * Member function for adding an element. 77 * Member function for inserting a single elements.
126 */ 78 * Implementors SHOULD see to performant implementations for corner cases.
127 int (*add)( 79 */
128 struct cx_list_s *list, 80 int (*insert_element)(
129 void const *elem
130 );
131
132 /**
133 * Member function for adding multiple elements.
134 */
135 size_t (*add_array)(
136 struct cx_list_s *list,
137 void const *array,
138 size_t n
139 );
140
141 /**
142 * Member function for inserting an element.
143 */
144 int (*insert)(
145 struct cx_list_s *list, 81 struct cx_list_s *list,
146 size_t index, 82 size_t index,
147 void const *elem 83 void const *data
84 );
85
86 /**
87 * Member function for inserting multiple elements.
88 * Implementors SHOULD see to performant implementations for corner cases.
89 */
90 size_t (*insert_array)(
91 struct cx_list_s *list,
92 size_t index,
93 void const *data,
94 size_t n
148 ); 95 );
149 96
150 /** 97 /**
151 * Member function for inserting an element relative to an iterator position. 98 * Member function for inserting an element relative to an iterator position.
152 */ 99 */
163 struct cx_list_s *list, 110 struct cx_list_s *list,
164 size_t index 111 size_t index
165 ); 112 );
166 113
167 /** 114 /**
115 * Member function for removing all elements.
116 */
117 void (*clear)(struct cx_list_s *list);
118
119 /**
120 * Member function for swapping two elements.
121 */
122 int (*swap)(
123 struct cx_list_s *list,
124 size_t i,
125 size_t j
126 );
127
128 /**
168 * Member function for element lookup. 129 * Member function for element lookup.
169 */ 130 */
170 void *(*at)( 131 void *(*at)(
171 struct cx_list_s const *list, 132 struct cx_list_s const *list,
172 size_t index 133 size_t index
173 ); 134 );
174 135
175 /** 136 /**
176 * Member function for finding an element. 137 * Member function for finding an element.
177 */ 138 */
178 size_t (*find)( 139 ssize_t (*find)(
179 struct cx_list_s const *list, 140 struct cx_list_s const *list,
180 void const *elem 141 void const *elem
181 ); 142 );
182 143
183 /** 144 /**
197 * Member function for reversing the order of the items. 158 * Member function for reversing the order of the items.
198 */ 159 */
199 void (*reverse)(struct cx_list_s *list); 160 void (*reverse)(struct cx_list_s *list);
200 161
201 /** 162 /**
202 * Returns an iterator pointing to the specified index. 163 * Member function for returning an iterator pointing to the specified index.
203 */ 164 */
204 struct cx_iterator_s (*iterator)( 165 struct cx_iterator_s (*iterator)(
205 struct cx_list_s const *list, 166 struct cx_list_s const *list,
206 size_t index 167 size_t index,
207 ); 168 bool backward
208
209 /**
210 * Returns a mutating iterator pointing to the specified index.
211 */
212 struct cx_mut_iterator_s (*mut_iterator)(
213 struct cx_list_s *list,
214 size_t index
215 ); 169 );
216 }; 170 };
217 171
218 /** 172 /**
219 * Common type for all list implementations. 173 * Common type for all list implementations.
220 */ 174 */
221 typedef struct cx_list_s CxList; 175 typedef struct cx_list_s CxList;
176
177 /**
178 * Advises the list to store copies of the objects (default mode of operation).
179 *
180 * Retrieving objects from this list will yield pointers to the copies stored
181 * within this list.
182 *
183 * @param list the list
184 * @see cxListStorePointers()
185 */
186 __attribute__((__nonnull__))
187 void cxListStoreObjects(CxList *list);
188
189 /**
190 * Advises the list to only store pointers to the objects.
191 *
192 * Retrieving objects from this list will yield the original pointers stored.
193 *
194 * @note This function forcibly sets the element size to the size of a pointer.
195 * Invoking this function on a non-empty list that already stores copies of
196 * objects is undefined.
197 *
198 * @param list the list
199 * @see cxListStoreObjects()
200 */
201 __attribute__((__nonnull__))
202 void cxListStorePointers(CxList *list);
203
204 /**
205 * Returns true, if this list is storing pointers instead of the actual data.
206 *
207 * @param list
208 * @return true, if this list is storing pointers
209 * @see cxListStorePointers()
210 */
211 __attribute__((__nonnull__))
212 static inline bool cxListIsStoringPointers(CxList const *list) {
213 return list->store_pointer;
214 }
215
216 /**
217 * Returns the number of elements currently stored in the list.
218 *
219 * @param list the list
220 * @return the number of currently stored elements
221 */
222 __attribute__((__nonnull__))
223 static inline size_t cxListSize(CxList const *list) {
224 return list->size;
225 }
222 226
223 /** 227 /**
224 * Adds an item to the end of the list. 228 * Adds an item to the end of the list.
225 * 229 *
226 * @param list the list 230 * @param list the list
231 __attribute__((__nonnull__)) 235 __attribute__((__nonnull__))
232 static inline int cxListAdd( 236 static inline int cxListAdd(
233 CxList *list, 237 CxList *list,
234 void const *elem 238 void const *elem
235 ) { 239 ) {
236 return list->cl->add(list, elem); 240 return list->cl->insert_element(list, list->size, elem);
237 } 241 }
238 242
239 /** 243 /**
240 * Adds multiple items to the end of the list. 244 * Adds multiple items to the end of the list.
241 * 245 *
242 * This method is more efficient than invoking cxListAdd() multiple times. 246 * This method is more efficient than invoking cxListAdd() multiple times.
243 * 247 *
244 * If there is not enough memory to add all elements, the returned value is 248 * If there is not enough memory to add all elements, the returned value is
245 * less than \p n. 249 * less than \p n.
250 *
251 * If this list is storing pointers instead of objects \p array is expected to
252 * be an array of pointers.
246 * 253 *
247 * @param list the list 254 * @param list the list
248 * @param array a pointer to the elements to add 255 * @param array a pointer to the elements to add
249 * @param n the number of elements to add 256 * @param n the number of elements to add
250 * @return the number of added elements 257 * @return the number of added elements
253 static inline size_t cxListAddArray( 260 static inline size_t cxListAddArray(
254 CxList *list, 261 CxList *list,
255 void const *array, 262 void const *array,
256 size_t n 263 size_t n
257 ) { 264 ) {
258 return list->cl->add_array(list, array, n); 265 return list->cl->insert_array(list, list->size, array, n);
259 } 266 }
260 267
261 /** 268 /**
262 * Inserts an item at the specified index. 269 * Inserts an item at the specified index.
263 * 270 *
275 static inline int cxListInsert( 282 static inline int cxListInsert(
276 CxList *list, 283 CxList *list,
277 size_t index, 284 size_t index,
278 void const *elem 285 void const *elem
279 ) { 286 ) {
280 return list->cl->insert(list, index, elem); 287 return list->cl->insert_element(list, index, elem);
288 }
289
290 /**
291 * Inserts multiple items to the list at the specified index.
292 * If \p index equals the list size, this is effectively cxListAddArray().
293 *
294 * This method is usually more efficient than invoking cxListInsert()
295 * multiple times.
296 *
297 * If there is not enough memory to add all elements, the returned value is
298 * less than \p n.
299 *
300 * If this list is storing pointers instead of objects \p array is expected to
301 * be an array of pointers.
302 *
303 * @param list the list
304 * @param index the index where to add the elements
305 * @param array a pointer to the elements to add
306 * @param n the number of elements to add
307 * @return the number of added elements
308 */
309 __attribute__((__nonnull__))
310 static inline size_t cxListInsertArray(
311 CxList *list,
312 size_t index,
313 void const *array,
314 size_t n
315 ) {
316 return list->cl->insert_array(list, index, array, n);
281 } 317 }
282 318
283 /** 319 /**
284 * Inserts an element after the current location of the specified iterator. 320 * Inserts an element after the current location of the specified iterator.
285 * 321 *
326 return ((struct cx_list_s *) iter->src_handle)->cl->insert_iter(iter, elem, 1); 362 return ((struct cx_list_s *) iter->src_handle)->cl->insert_iter(iter, elem, 1);
327 } 363 }
328 364
329 /** 365 /**
330 * Removes the element at the specified index. 366 * Removes the element at the specified index.
367 *
368 * If an element destructor function is specified, it is called before
369 * removing the element.
370 *
331 * @param list the list 371 * @param list the list
332 * @param index the index of the element 372 * @param index the index of the element
333 * @return zero on success, non-zero if the index is out of bounds 373 * @return zero on success, non-zero if the index is out of bounds
334 */ 374 */
335 __attribute__((__nonnull__)) 375 __attribute__((__nonnull__))
339 ) { 379 ) {
340 return list->cl->remove(list, index); 380 return list->cl->remove(list, index);
341 } 381 }
342 382
343 /** 383 /**
384 * Removes all elements from this list.
385 *
386 * If an element destructor function is specified, it is called for each
387 * element before removing them.
388 *
389 * @param list the list
390 */
391 __attribute__((__nonnull__))
392 static inline void cxListClear(CxList *list) {
393 list->cl->clear(list);
394 }
395
396 /**
397 * Swaps two items in the list.
398 *
399 * Implementations should only allocate temporary memory for the swap, if
400 * it is necessary.
401 *
402 * @param list the list
403 * @param i the index of the first element
404 * @param j the index of the second element
405 * @return zero on success, non-zero if one of the indices is out of bounds
406 */
407 __attribute__((__nonnull__))
408 static inline int cxListSwap(
409 CxList *list,
410 size_t i,
411 size_t j
412 ) {
413 return list->cl->swap(list, i, j);
414 }
415
416 /**
344 * Returns a pointer to the element at the specified index. 417 * Returns a pointer to the element at the specified index.
345 * 418 *
346 * @param list the list 419 * @param list the list
347 * @param index the index of the element 420 * @param index the index of the element
348 * @return a pointer to the element or \c NULL if the index is out of bounds 421 * @return a pointer to the element or \c NULL if the index is out of bounds
365 * @param list the list 438 * @param list the list
366 * @param index the index where the iterator shall point at 439 * @param index the index where the iterator shall point at
367 * @return a new iterator 440 * @return a new iterator
368 */ 441 */
369 __attribute__((__nonnull__, __warn_unused_result__)) 442 __attribute__((__nonnull__, __warn_unused_result__))
370 static inline CxIterator cxListIterator( 443 static inline CxIterator cxListIteratorAt(
371 CxList const *list, 444 CxList const *list,
372 size_t index 445 size_t index
373 ) { 446 ) {
374 return list->cl->iterator(list, index); 447 return list->cl->iterator(list, index, false);
448 }
449
450 /**
451 * Returns a backwards iterator pointing to the item at the specified index.
452 *
453 * The returned iterator is position-aware.
454 *
455 * If the index is out of range, a past-the-end iterator will be returned.
456 *
457 * @param list the list
458 * @param index the index where the iterator shall point at
459 * @return a new iterator
460 */
461 __attribute__((__nonnull__, __warn_unused_result__))
462 static inline CxIterator cxListBackwardsIteratorAt(
463 CxList const *list,
464 size_t index
465 ) {
466 return list->cl->iterator(list, index, true);
375 } 467 }
376 468
377 /** 469 /**
378 * Returns a mutating iterator pointing to the item at the specified index. 470 * Returns a mutating iterator pointing to the item at the specified index.
379 * 471 *
384 * @param list the list 476 * @param list the list
385 * @param index the index where the iterator shall point at 477 * @param index the index where the iterator shall point at
386 * @return a new iterator 478 * @return a new iterator
387 */ 479 */
388 __attribute__((__nonnull__, __warn_unused_result__)) 480 __attribute__((__nonnull__, __warn_unused_result__))
389 static inline CxMutIterator cxListMutIterator( 481 CxMutIterator cxListMutIteratorAt(
390 CxList *list, 482 CxList *list,
391 size_t index 483 size_t index
392 ) { 484 );
393 return list->cl->mut_iterator(list, index); 485
394 } 486 /**
487 * Returns a mutating backwards iterator pointing to the item at the
488 * specified index.
489 *
490 * The returned iterator is position-aware.
491 *
492 * If the index is out of range, a past-the-end iterator will be returned.
493 *
494 * @param list the list
495 * @param index the index where the iterator shall point at
496 * @return a new iterator
497 */
498 __attribute__((__nonnull__, __warn_unused_result__))
499 CxMutIterator cxListMutBackwardsIteratorAt(
500 CxList *list,
501 size_t index
502 );
395 503
396 /** 504 /**
397 * Returns an iterator pointing to the first item of the list. 505 * Returns an iterator pointing to the first item of the list.
398 * 506 *
399 * The returned iterator is position-aware. 507 * The returned iterator is position-aware.
402 * 510 *
403 * @param list the list 511 * @param list the list
404 * @return a new iterator 512 * @return a new iterator
405 */ 513 */
406 __attribute__((__nonnull__, __warn_unused_result__)) 514 __attribute__((__nonnull__, __warn_unused_result__))
407 static inline CxIterator cxListBegin(CxList const *list) { 515 static inline CxIterator cxListIterator(CxList const *list) {
408 return list->cl->iterator(list, 0); 516 return list->cl->iterator(list, 0, false);
409 } 517 }
410 518
411 /** 519 /**
412 * Returns a mutating iterator pointing to the first item of the list. 520 * Returns a mutating iterator pointing to the first item of the list.
413 * 521 *
417 * 525 *
418 * @param list the list 526 * @param list the list
419 * @return a new iterator 527 * @return a new iterator
420 */ 528 */
421 __attribute__((__nonnull__, __warn_unused_result__)) 529 __attribute__((__nonnull__, __warn_unused_result__))
422 static inline CxMutIterator cxListBeginMut(CxList *list) { 530 static inline CxMutIterator cxListMutIterator(CxList *list) {
423 return list->cl->mut_iterator(list, 0); 531 return cxListMutIteratorAt(list, 0);
532 }
533
534
535 /**
536 * Returns a backwards iterator pointing to the last item of the list.
537 *
538 * The returned iterator is position-aware.
539 *
540 * If the list is empty, a past-the-end iterator will be returned.
541 *
542 * @param list the list
543 * @return a new iterator
544 */
545 __attribute__((__nonnull__, __warn_unused_result__))
546 static inline CxIterator cxListBackwardsIterator(CxList const *list) {
547 return list->cl->iterator(list, list->size - 1, true);
548 }
549
550 /**
551 * Returns a mutating backwards iterator pointing to the last item of the list.
552 *
553 * The returned iterator is position-aware.
554 *
555 * If the list is empty, a past-the-end iterator will be returned.
556 *
557 * @param list the list
558 * @return a new iterator
559 */
560 __attribute__((__nonnull__, __warn_unused_result__))
561 static inline CxMutIterator cxListMutBackwardsIterator(CxList *list) {
562 return cxListMutBackwardsIteratorAt(list, list->size - 1);
424 } 563 }
425 564
426 /** 565 /**
427 * Returns the index of the first element that equals \p elem. 566 * Returns the index of the first element that equals \p elem.
428 * 567 *
429 * Determining equality is performed by the list's comparator function. 568 * Determining equality is performed by the list's comparator function.
430 * 569 *
431 * @param list the list 570 * @param list the list
432 * @param elem the element to find 571 * @param elem the element to find
433 * @return the index of the element or \c (size+1) if the element is not found 572 * @return the index of the element or a negative
434 */ 573 * value when the element is not found
435 __attribute__((__nonnull__)) 574 */
436 static inline size_t cxListFind( 575 __attribute__((__nonnull__))
576 static inline ssize_t cxListFind(
437 CxList const *list, 577 CxList const *list,
438 void const *elem 578 void const *elem
439 ) { 579 ) {
440 return list->cl->find(list, elem); 580 return list->cl->find(list, elem);
441 } 581 }

mercurial