src/linked_list.c

changeset 473
1bd4b8c28722
parent 469
0458bff0b1cd
child 474
9c1fccda16bc
     1.1 --- a/src/linked_list.c	Fri Oct 08 18:58:49 2021 +0200
     1.2 +++ b/src/linked_list.c	Fri Oct 08 19:47:31 2021 +0200
     1.3 @@ -36,6 +36,8 @@
     1.4  #define CX_LL_PTR(cur, off) (*(void**)(((char*)cur)+off))
     1.5  
     1.6  void *cx_linked_list_at(void *start, size_t start_index, ptrdiff_t loc_advance, size_t index) {
     1.7 +    assert(start != NULL);
     1.8 +    assert(loc_advance >= 0);
     1.9      size_t i = start_index;
    1.10      void *cur = start;
    1.11      while (i != index && cur != NULL) {
    1.12 @@ -46,6 +48,7 @@
    1.13  }
    1.14  
    1.15  void *cx_linked_list_last(void *begin, ptrdiff_t loc_next) {
    1.16 +    assert(loc_next >= 0);
    1.17      if (begin == NULL)
    1.18          return NULL;
    1.19  
    1.20 @@ -58,7 +61,21 @@
    1.21      return last;
    1.22  }
    1.23  
    1.24 +void *cx_linked_list_prev(void *begin, ptrdiff_t loc_next, void *node) {
    1.25 +    assert(begin != NULL);
    1.26 +    assert(loc_next >= 0);
    1.27 +    if (begin == node) return NULL;
    1.28 +    void *cur = begin;
    1.29 +    void *next;
    1.30 +    while (1) {
    1.31 +        next = CX_LL_PTR(cur, loc_next);
    1.32 +        if (next == node) return cur;
    1.33 +        cur = next;
    1.34 +    }
    1.35 +}
    1.36 +
    1.37  void cx_linked_list_add(void **begin, void **end, ptrdiff_t loc_prev, ptrdiff_t loc_next, void *new_node) {
    1.38 +    assert(loc_next >= 0);
    1.39      void *last;
    1.40      if (end == NULL) {
    1.41          assert(begin != NULL);
    1.42 @@ -85,7 +102,48 @@
    1.43      }
    1.44  }
    1.45  
    1.46 +void *cx_linked_list_remove(void **begin, void **end, ptrdiff_t loc_prev, ptrdiff_t loc_next, void *node) {
    1.47 +    assert(loc_next >= 0);
    1.48 +    assert(loc_prev >= 0 || begin != NULL);
    1.49 +
    1.50 +    // find adjacent nodes
    1.51 +    void *next = CX_LL_PTR(node, loc_next);
    1.52 +    void *prev;
    1.53 +    if (loc_prev >= 0) {
    1.54 +        prev = CX_LL_PTR(node, loc_prev);
    1.55 +    } else {
    1.56 +        prev = cx_linked_list_prev(*begin, loc_next, node);
    1.57 +    }
    1.58 +
    1.59 +    // update links of adjacent nodes
    1.60 +    if (prev != NULL) {
    1.61 +        CX_LL_PTR(prev, loc_next) = next;
    1.62 +    }
    1.63 +    if (next != NULL && loc_prev >= 0) {
    1.64 +        CX_LL_PTR(next, loc_prev) = prev;
    1.65 +    }
    1.66 +
    1.67 +    // erase links of the target node
    1.68 +    CX_LL_PTR(node, loc_next) = NULL;
    1.69 +    if (loc_prev >= 0) {
    1.70 +        CX_LL_PTR(node, loc_prev) = NULL;
    1.71 +    }
    1.72 +
    1.73 +    // update begin, if required
    1.74 +    if (*begin == node) {
    1.75 +        *begin = next;
    1.76 +    }
    1.77 +
    1.78 +    // update end, if required
    1.79 +    if (end != NULL && *end == node) {
    1.80 +        *end = prev;
    1.81 +    }
    1.82 +
    1.83 +    return prev == NULL ? next : prev;
    1.84 +}
    1.85 +
    1.86  size_t cx_linked_list_size(void *node, ptrdiff_t loc_next) {
    1.87 +    assert(loc_next >= 0);
    1.88      size_t size = 0;
    1.89      while (node != NULL) {
    1.90          node = CX_LL_PTR(node, loc_next);
    1.91 @@ -149,6 +207,9 @@
    1.92  void cx_linked_list_sort(void **begin, void **end, ptrdiff_t loc_prev, ptrdiff_t loc_next,
    1.93                           ptrdiff_t loc_data, int follow_ptr, CxListComparator cmp_func) {
    1.94      assert(begin != NULL);
    1.95 +    assert(loc_next >= 0);
    1.96 +    assert(loc_data >= 0);
    1.97 +    assert(cmp_func);
    1.98  
    1.99      void *lc, *ls, *le, *re;
   1.100  
   1.101 @@ -201,6 +262,32 @@
   1.102  #undef ll_next
   1.103  #undef ll_data
   1.104  
   1.105 +void cx_linked_list_reverse(void **begin, void **end, ptrdiff_t loc_prev, ptrdiff_t loc_next) {
   1.106 +    assert(begin != NULL);
   1.107 +    assert(loc_next >= 0);
   1.108 +
   1.109 +    // swap all links
   1.110 +    void *prev = NULL;
   1.111 +    void *cur = *begin;
   1.112 +    while (cur != NULL) {
   1.113 +        void *next = CX_LL_PTR(cur, loc_next);
   1.114 +
   1.115 +        CX_LL_PTR(cur, loc_next) = prev;
   1.116 +        if (loc_prev >= 0) {
   1.117 +            CX_LL_PTR(cur, loc_prev) = next;
   1.118 +        }
   1.119 +
   1.120 +        prev = cur;
   1.121 +        cur = next;
   1.122 +    }
   1.123 +
   1.124 +    // update begin and end
   1.125 +    if (end != NULL) {
   1.126 +        *end = *begin;
   1.127 +    }
   1.128 +    *begin = prev;
   1.129 +}
   1.130 +
   1.131  /* HIGH LEVEL LINKED LIST IMPLEMENTATION */
   1.132  
   1.133  typedef struct cx_linked_list_node cx_linked_list_node;

mercurial