# HG changeset patch # User Mike Becker # Date 1688402239 -7200 # Node ID 9c097dabba2c2f00026f16b13004ca993a2758e1 # Parent 9fecb2769d32e9fe7f0d93fd74a9808e07a6a8b0 add documentation for the lists diff -r 9fecb2769d32 -r 9c097dabba2c docs/src/features.md --- a/docs/src/features.md Sat Jul 01 14:29:16 2023 +0200 +++ b/docs/src/features.md Mon Jul 03 18:37:19 2023 +0200 @@ -209,14 +209,100 @@ *Header file:* [list.h](api/list_8h.html) +This header defines a common interface for all list implementations, which is basically as simple as the following +structure. +```c +struct cx_list_s { + CX_COLLECTION_MEMBERS // size, capacity, etc. + cx_list_class const *cl; // The list class definition +}; +``` +The actual structure contains one more class pointer that is used when wrapping a list into a pointer aware list +with `cxListStorePointers()`. What this means, is that - if you want to implement your own list structure - you +only need to cover the case where the list is storing copies of your objects. + +UCX comes with two common list implementations (linked list and array list) that should cover most use cases. +But if you feel the need to implement an own list, the only thing you need to do is to define a struct where +`struct cx_list_s`, and set an appropriate list class that implements the functionality. +It is strongly recommended that this class is shared among all instances of the same list type, because otherwise +the `cxListCompare` function cannot use the optimized implementation of your class and will instead fall back to +using iterators to compare the contents element-wise. + ### Linked List *Header file:* [linked_list.h](api/linked__list_8h.html) +On top of implementing the list interface, this header also defines several low-level functions that +work with arbitrary structures. +Low-level functions, in contrast to the high-level list interface, can easily be recognized by their snake-casing. +The function `cx_linked_list_at`, for example, implements a similar functionality like `cxListAt`, but operates +on arbitrary structures. +The following snippet shows how it is used. +All other low-level functions work similarly. +```c +struct node { + node *next; + node *prev; + int data; +}; + +const ptrdiff_t loc_prev = offsetof(struct node, prev); +const ptrdiff_t loc_next = offsetof(struct node, next); +const ptrdiff_t loc_data = offsetof(struct node, data); + +struct node a = {0}, b = {0}, c = {0}, d = {0}; +cx_linked_list_link(&a, &b, loc_prev, loc_next); +cx_linked_list_link(&b, &c, loc_prev, loc_next); +cx_linked_list_link(&c, &d, loc_prev, loc_next); + +cx_linked_list_at(&a, 0, loc_next, 2); // returns pointer to c +``` + ### Array List *Header file:* [array_list.h](api/array__list_8h.html) +Since low-level array lists are just plain arrays, there is no need for such many low-level functions as for linked +lists. +However, there is one extremely powerful function that can be used for several complex tasks: `cx_array_copy`. +The full signature is shown below: +```c +enum cx_array_copy_result cx_array_copy( + void **target, + size_t *size, + size_t *capacity, // optional + size_t index, + void const *src, + size_t elem_size, + size_t elem_count, + struct cx_array_reallocator_s *reallocator // optional +); +``` +The `target` argument is a pointer to the target array pointer. +The reason for this additional indirection is that - given that you provide a `reallocator` - this function writes +back the pointer to the possibly reallocated array. +THe next two arguments are pointers to the `size` and `capacity` of the target array. +Tracking the capacity is optional. +If you do not specify a pointer for the capacity, automatic reallocation of the array is entirely disabled (i.e. it +does not make sense to specify a `reallocator` then). +In this case, the function cannot copy more than `size-index` elements and if you try, it will return +`CX_ARRAY_COPY_REALLOC_NOT_SUPPORTED` and do nothing. + +On a successful invocation, the function copies `elem_count` number of elements, each of size `elem_size` from +`src` to `*target` and uses the `reallocator` to extend the array when necessary. +Finally, the size, capacity, and the pointer to the array are all updated and the function returns +`CX_ARRAY_COPY_SUCCESS`. + +The third, but extremely rare, return code is `CX_ARRAY_COPY_REALLOC_FAILED` and speaks for itself. + +A few things to note: +* `*target` and `src` can point to the same memory region, effectively copying elements within the array with `memmove` +* `*target` does not need to point to the start of the array, but `size` and `capacity` always start counting from the + position, `*target` points to - in this scenario, specifying a `reallocator` is forbidden for obvious reasons +* `index` does not need to be within size of the current array, if `capacity` is specified +* `index` does not even need to be within the capacity of the array, if `reallocator` is specified + + ## Map *Header file:* [map.h](api/map_8h.html)