diff -r ec1f2015ec79 -r 75da57d4634e src/linked_list.c --- a/src/linked_list.c Sun Oct 06 19:17:41 2024 +0200 +++ b/src/linked_list.c Mon Oct 07 20:20:21 2024 +0200 @@ -91,7 +91,7 @@ do { void *current = ll_data(node); if (cmp_func(current, elem) == 0) { - *result = (void*) node; + *result = (void *) node; return index; } node = ll_advance(node); @@ -336,19 +336,22 @@ } } -void cx_linked_list_remove( +size_t cx_linked_list_remove_chain( void **begin, void **end, ptrdiff_t loc_prev, ptrdiff_t loc_next, - void *node + void *node, + size_t num ) { assert(node != NULL); assert(loc_next >= 0); assert(loc_prev >= 0 || begin != NULL); + // easy exit + if (num == 0) return 0; + // find adjacent nodes - void *next = ll_next(node); void *prev; if (loc_prev >= 0) { prev = ll_prev(node); @@ -356,6 +359,12 @@ prev = cx_linked_list_prev(*begin, loc_next, node); } + void *next = ll_next(node); + size_t removed = 1; + for (; removed < num && next != NULL ; removed++) { + next = ll_next(next); + } + // update next pointer of prev node, or set begin if (prev == NULL) { if (begin != NULL) { @@ -373,6 +382,8 @@ } else if (loc_prev >= 0) { ll_prev(next) = prev; } + + return removed; } size_t cx_linked_list_size( @@ -442,7 +453,7 @@ ll_next(sorted[length - 1]) = NULL; *begin = sorted[0]; - *end = sorted[length-1]; + *end = sorted[length - 1]; if (sorted != sbo) { free(sorted); } @@ -733,30 +744,63 @@ return inserted; } -static int cx_ll_remove( +static size_t cx_ll_remove( struct cx_list_s *list, - size_t index + size_t index, + size_t num, + void *targetbuf ) { cx_linked_list *ll = (cx_linked_list *) list; cx_linked_list_node *node = cx_ll_node_at(ll, index); // out-of-bounds check - if (node == NULL) return 1; - - // element destruction - cx_invoke_destructor(list, node->payload); + if (node == NULL) return 0; // remove - cx_linked_list_remove((void **) &ll->begin, (void **) &ll->end, - CX_LL_LOC_PREV, CX_LL_LOC_NEXT, node); + size_t removed = cx_linked_list_remove_chain( + (void **) &ll->begin, + (void **) &ll->end, + CX_LL_LOC_PREV, + CX_LL_LOC_NEXT, + node, + num + ); // adjust size - list->collection.size--; + list->collection.size -= removed; + + // copy or destroy the removed chain + if (targetbuf == NULL) { + cx_linked_list_node *n = node; + cx_for_n(i, removed) { + // element destruction + cx_invoke_destructor(list, n->payload); + + // free the node + cxFree(list->collection.allocator, n); - // free and return - cxFree(list->collection.allocator, node); + // next + n = n->next; + } + } else { + char *dest = targetbuf; + cx_linked_list_node *n = node; + cx_for_n(i, removed) { + // copy payload + memcpy(dest, n->payload, list->collection.elem_size); - return 0; + // advance target buffer + dest += list->collection.elem_size; + + // free the node + cxFree(list->collection.allocator, n); + + // next + n = n->next; + } + } + + return removed; } static void cx_ll_clear(struct cx_list_s *list) {