src/linked_list.c

changeset 664
af5bf4603a5d
parent 662
d0d95740071b
child 666
b5dd654deb3b
     1.1 --- a/src/linked_list.c	Sun Mar 05 10:55:32 2023 +0100
     1.2 +++ b/src/linked_list.c	Tue Mar 14 20:25:24 2023 +0100
     1.3 @@ -569,6 +569,11 @@
     1.4      // out-of-bounds check
     1.5      if (node == NULL) return 1;
     1.6  
     1.7 +    // element destruction
     1.8 +    if (list->content_destructor_type != CX_DESTRUCTOR_NONE) {
     1.9 +        cx_list_invoke_destructor(list, node->payload);
    1.10 +    }
    1.11 +
    1.12      // remove
    1.13      cx_linked_list_remove((void **) &ll->begin, (void **) &ll->end,
    1.14                            CX_LL_LOC_PREV, CX_LL_LOC_NEXT, node);
    1.15 @@ -582,6 +587,48 @@
    1.16      return 0;
    1.17  }
    1.18  
    1.19 +static void cx_ll_clear(struct cx_list_s *list) {
    1.20 +    if (list->size == 0) return;
    1.21 +
    1.22 +    cx_linked_list *ll = (cx_linked_list *) list;
    1.23 +    cx_linked_list_node *node = ll->begin;
    1.24 +
    1.25 +    // looks super redundant, but avoids repeatedly checking
    1.26 +    // the destructor type for each element
    1.27 +    switch (list->content_destructor_type) {
    1.28 +        case CX_DESTRUCTOR_SIMPLE: {
    1.29 +            while (node != NULL) {
    1.30 +                list->simple_destructor(node->payload);
    1.31 +                cx_linked_list_node *next = node->next;
    1.32 +                cxFree(list->allocator, node);
    1.33 +                node = next;
    1.34 +            }
    1.35 +            break;
    1.36 +        }
    1.37 +        case CX_DESTRUCTOR_ADVANCED: {
    1.38 +            while (node != NULL) {
    1.39 +                list->advanced_destructor.func(list->advanced_destructor.data,
    1.40 +                                               node->payload);
    1.41 +                cx_linked_list_node *next = node->next;
    1.42 +                cxFree(list->allocator, node);
    1.43 +                node = next;
    1.44 +            }
    1.45 +            break;
    1.46 +        }
    1.47 +        case CX_DESTRUCTOR_NONE: {
    1.48 +            while (node != NULL) {
    1.49 +                cx_linked_list_node *next = node->next;
    1.50 +                cxFree(list->allocator, node);
    1.51 +                node = next;
    1.52 +            }
    1.53 +            break;
    1.54 +        }
    1.55 +    }
    1.56 +
    1.57 +    ll->begin = ll->end = NULL;
    1.58 +    list->size = 0;
    1.59 +}
    1.60 +
    1.61  #ifndef CX_LINKED_LIST_SWAP_SBO_SIZE
    1.62  #define CX_LINKED_LIST_SWAP_SBO_SIZE 16
    1.63  #endif
    1.64 @@ -753,13 +800,17 @@
    1.65      if (itbase->remove) {
    1.66          itbase->remove = false;
    1.67          struct cx_mut_iterator_s *iter = it;
    1.68 +        struct cx_list_s *list = iter->src_handle;
    1.69          cx_linked_list *ll = iter->src_handle;
    1.70          cx_linked_list_node *node = iter->elem_handle;
    1.71          iter->elem_handle = node->next;
    1.72 +        if (list->content_destructor_type != CX_DESTRUCTOR_NONE) {
    1.73 +            cx_list_invoke_destructor(list, node->payload);
    1.74 +        }
    1.75          cx_linked_list_remove((void **) &ll->begin, (void **) &ll->end,
    1.76                                CX_LL_LOC_PREV, CX_LL_LOC_NEXT, node);
    1.77 -        ll->base.size--;
    1.78 -        cxFree(ll->base.allocator, node);
    1.79 +        list->size--;
    1.80 +        cxFree(list->allocator, node);
    1.81      } else {
    1.82          struct cx_iterator_s *iter = it;
    1.83          iter->index++;
    1.84 @@ -773,14 +824,18 @@
    1.85      if (itbase->remove) {
    1.86          itbase->remove = false;
    1.87          struct cx_mut_iterator_s *iter = it;
    1.88 +        struct cx_list_s *list = iter->src_handle;
    1.89          cx_linked_list *ll = iter->src_handle;
    1.90          cx_linked_list_node *node = iter->elem_handle;
    1.91          iter->elem_handle = node->prev;
    1.92          iter->index--;
    1.93 +        if (list->content_destructor_type != CX_DESTRUCTOR_NONE) {
    1.94 +            cx_list_invoke_destructor(list, node->payload);
    1.95 +        }
    1.96          cx_linked_list_remove((void **) &ll->begin, (void **) &ll->end,
    1.97                                CX_LL_LOC_PREV, CX_LL_LOC_NEXT, node);
    1.98 -        ll->base.size--;
    1.99 -        cxFree(ll->base.allocator, node);
   1.100 +        list->size--;
   1.101 +        cxFree(list->allocator, node);
   1.102      } else {
   1.103          struct cx_iterator_s *iter = it;
   1.104          iter->index--;
   1.105 @@ -861,6 +916,7 @@
   1.106          cx_ll_insert_array,
   1.107          cx_ll_insert_iter,
   1.108          cx_ll_remove,
   1.109 +        cx_ll_clear,
   1.110          cx_ll_swap,
   1.111          cx_ll_at,
   1.112          cx_ll_find,

mercurial