diff -r 18f964adad1b -r 1bd4b8c28722 src/linked_list.c --- a/src/linked_list.c Fri Oct 08 18:58:49 2021 +0200 +++ b/src/linked_list.c Fri Oct 08 19:47:31 2021 +0200 @@ -36,6 +36,8 @@ #define CX_LL_PTR(cur, off) (*(void**)(((char*)cur)+off)) void *cx_linked_list_at(void *start, size_t start_index, ptrdiff_t loc_advance, size_t index) { + assert(start != NULL); + assert(loc_advance >= 0); size_t i = start_index; void *cur = start; while (i != index && cur != NULL) { @@ -46,6 +48,7 @@ } void *cx_linked_list_last(void *begin, ptrdiff_t loc_next) { + assert(loc_next >= 0); if (begin == NULL) return NULL; @@ -58,7 +61,21 @@ return last; } +void *cx_linked_list_prev(void *begin, ptrdiff_t loc_next, void *node) { + assert(begin != NULL); + assert(loc_next >= 0); + if (begin == node) return NULL; + void *cur = begin; + void *next; + while (1) { + next = CX_LL_PTR(cur, loc_next); + if (next == node) return cur; + cur = next; + } +} + void cx_linked_list_add(void **begin, void **end, ptrdiff_t loc_prev, ptrdiff_t loc_next, void *new_node) { + assert(loc_next >= 0); void *last; if (end == NULL) { assert(begin != NULL); @@ -85,7 +102,48 @@ } } +void *cx_linked_list_remove(void **begin, void **end, ptrdiff_t loc_prev, ptrdiff_t loc_next, void *node) { + assert(loc_next >= 0); + assert(loc_prev >= 0 || begin != NULL); + + // find adjacent nodes + void *next = CX_LL_PTR(node, loc_next); + void *prev; + if (loc_prev >= 0) { + prev = CX_LL_PTR(node, loc_prev); + } else { + prev = cx_linked_list_prev(*begin, loc_next, node); + } + + // update links of adjacent nodes + if (prev != NULL) { + CX_LL_PTR(prev, loc_next) = next; + } + if (next != NULL && loc_prev >= 0) { + CX_LL_PTR(next, loc_prev) = prev; + } + + // erase links of the target node + CX_LL_PTR(node, loc_next) = NULL; + if (loc_prev >= 0) { + CX_LL_PTR(node, loc_prev) = NULL; + } + + // update begin, if required + if (*begin == node) { + *begin = next; + } + + // update end, if required + if (end != NULL && *end == node) { + *end = prev; + } + + return prev == NULL ? next : prev; +} + size_t cx_linked_list_size(void *node, ptrdiff_t loc_next) { + assert(loc_next >= 0); size_t size = 0; while (node != NULL) { node = CX_LL_PTR(node, loc_next); @@ -149,6 +207,9 @@ void cx_linked_list_sort(void **begin, void **end, ptrdiff_t loc_prev, ptrdiff_t loc_next, ptrdiff_t loc_data, int follow_ptr, CxListComparator cmp_func) { assert(begin != NULL); + assert(loc_next >= 0); + assert(loc_data >= 0); + assert(cmp_func); void *lc, *ls, *le, *re; @@ -201,6 +262,32 @@ #undef ll_next #undef ll_data +void cx_linked_list_reverse(void **begin, void **end, ptrdiff_t loc_prev, ptrdiff_t loc_next) { + assert(begin != NULL); + assert(loc_next >= 0); + + // swap all links + void *prev = NULL; + void *cur = *begin; + while (cur != NULL) { + void *next = CX_LL_PTR(cur, loc_next); + + CX_LL_PTR(cur, loc_next) = prev; + if (loc_prev >= 0) { + CX_LL_PTR(cur, loc_prev) = next; + } + + prev = cur; + cur = next; + } + + // update begin and end + if (end != NULL) { + *end = *begin; + } + *begin = prev; +} + /* HIGH LEVEL LINKED LIST IMPLEMENTATION */ typedef struct cx_linked_list_node cx_linked_list_node;