add cx_linked_list_compare() and simplifies some tests

Tue, 28 Dec 2021 14:16:04 +0100

author
Mike Becker <universe@uap-core.de>
date
Tue, 28 Dec 2021 14:16:04 +0100
changeset 486
d7ca126eab7f
parent 485
6a86ad3d8c03
child 487
4bd19279778c

add cx_linked_list_compare() and simplifies some tests

src/cx/linked_list.h file | annotate | diff | comparison | revisions
src/linked_list.c file | annotate | diff | comparison | revisions
test/test_list.c file | annotate | diff | comparison | revisions
     1.1 --- a/src/cx/linked_list.h	Mon Dec 27 17:16:32 2021 +0100
     1.2 +++ b/src/cx/linked_list.h	Tue Dec 28 14:16:04 2021 +0100
     1.3 @@ -382,6 +382,28 @@
     1.4          CxListComparator cmp_func
     1.5  ) __attribute__((__nonnull__(1, 7)));
     1.6  
     1.7 +
     1.8 +/**
     1.9 + * Compares two lists element wise.
    1.10 + *
    1.11 + * @param begin_left the begin of the left list (\c NULL denotes an empty list)
    1.12 + * @param begin_right the begin of the right list  (\c NULL denotes an empty list)
    1.13 + * @param loc_advance the location of the pointer to advance
    1.14 + * @param loc_data the location of the \c data pointer within your node struct
    1.15 + * @param follow_ptr \c false if the pointer denoted by \p loc_data shall be passed to the \p cmp_func.
    1.16 + * If \c true, the data at \p loc_data is assumed to be a pointer, dereferenced, and then passed to \p cmp_func.
    1.17 + * @param cmp_func the function to compare the elements
    1.18 + * @return
    1.19 + */
    1.20 +int cx_linked_list_compare(
    1.21 +        void *begin_left,
    1.22 +        void *begin_right,
    1.23 +        ptrdiff_t loc_advance,
    1.24 +        ptrdiff_t loc_data,
    1.25 +        int follow_ptr,
    1.26 +        CxListComparator cmp_func
    1.27 +) __attribute__((__nonnull__(6)));
    1.28 +
    1.29  /**
    1.30   * Reverses the order of the nodes in a linked list.
    1.31   *
     2.1 --- a/src/linked_list.c	Mon Dec 27 17:16:32 2021 +0100
     2.2 +++ b/src/linked_list.c	Tue Dec 28 14:16:04 2021 +0100
     2.3 @@ -396,6 +396,28 @@
     2.4      }
     2.5  }
     2.6  
     2.7 +int cx_linked_list_compare(
     2.8 +        void *begin_left,
     2.9 +        void *begin_right,
    2.10 +        ptrdiff_t loc_advance,
    2.11 +        ptrdiff_t loc_data,
    2.12 +        int follow_ptr,
    2.13 +        CxListComparator cmp_func
    2.14 +) {
    2.15 +    void *left = begin_left, *right = begin_right;
    2.16 +
    2.17 +    while (left != NULL && right != NULL) {
    2.18 +        int result = cmp_func(ll_data(left), ll_data(right));
    2.19 +        if (result != 0) return result;
    2.20 +        left = ll_advance(left);
    2.21 +        right = ll_advance(right);
    2.22 +    }
    2.23 +
    2.24 +    if (left != NULL) { return 1; }
    2.25 +    else if (right != NULL) { return -1; }
    2.26 +    else { return 0; }
    2.27 +}
    2.28 +
    2.29  void cx_linked_list_reverse(
    2.30          void **begin,
    2.31          void **end,
     3.1 --- a/test/test_list.c	Mon Dec 27 17:16:32 2021 +0100
     3.2 +++ b/test/test_list.c	Tue Dec 28 14:16:04 2021 +0100
     3.3 @@ -30,20 +30,55 @@
     3.4  #include "test_config.h"
     3.5  #include "util_allocator.h"
     3.6  
     3.7 -int cmp_int(int const *l, int const *r) {
     3.8 +int cmp_int(
     3.9 +        int const *l,
    3.10 +        int const *r
    3.11 +) {
    3.12      int left = *l, right = *r;
    3.13      return left == right ? 0 : (left < right ? -1 : 1);
    3.14  }
    3.15  
    3.16 +struct node {
    3.17 +    struct node *next;
    3.18 +    struct node *prev;
    3.19 +    int data;
    3.20 +};
    3.21 +
    3.22 +#define nd(name) name = {0}
    3.23 +
    3.24 +const ptrdiff_t loc_prev = offsetof(struct node, prev);
    3.25 +const ptrdiff_t loc_next = offsetof(struct node, next);
    3.26 +const ptrdiff_t loc_data = offsetof(struct node, data);
    3.27 +
    3.28 +struct node *create_test_data(
    3.29 +        size_t n,
    3.30 +        const int data[]
    3.31 +) {
    3.32 +    if (n == 0) return NULL;
    3.33 +    struct node *begin = calloc(1, sizeof(struct node));
    3.34 +    struct node *prev = begin;
    3.35 +    if (data) begin->data = data[0];
    3.36 +    for (size_t i = 1; i < n; i++) {
    3.37 +        struct node *node = calloc(1, sizeof(struct node));
    3.38 +        if (data) node->data = data[i];
    3.39 +        cx_linked_list_link(prev, node, loc_prev, loc_next);
    3.40 +        prev = node;
    3.41 +    }
    3.42 +    return begin;
    3.43 +}
    3.44 +
    3.45 +void destroy_test_data(struct node *begin) {
    3.46 +    struct node *node = begin;
    3.47 +    while (node) {
    3.48 +        struct node *next = node->next;
    3.49 +        free(node);
    3.50 +        node = next;
    3.51 +    }
    3.52 +}
    3.53 +
    3.54  void test_linked_list_link_unlink(void) {
    3.55 -    struct node {
    3.56 -        void *next;
    3.57 -        void *prev;
    3.58 -    };
    3.59 -    const ptrdiff_t loc_prev = offsetof(struct node, prev);
    3.60 -    const ptrdiff_t loc_next = offsetof(struct node, next);
    3.61  
    3.62 -    struct node a = {NULL, NULL}, b = {NULL, NULL};
    3.63 +    struct node nd(a), nd(b), nd(c);
    3.64  
    3.65      cx_linked_list_link(&a, &b, loc_prev, loc_next);
    3.66      CU_ASSERT_PTR_NULL(a.prev)
    3.67 @@ -57,7 +92,6 @@
    3.68      CU_ASSERT_PTR_NULL(b.prev)
    3.69      CU_ASSERT_PTR_NULL(b.next)
    3.70  
    3.71 -    struct node c = {NULL, NULL};
    3.72      cx_linked_list_link(&b, &c, loc_prev, loc_next);
    3.73      cx_linked_list_link(&a, &b, loc_prev, loc_next);
    3.74      cx_linked_list_unlink(&b, &c, loc_prev, loc_next);
    3.75 @@ -70,22 +104,10 @@
    3.76  }
    3.77  
    3.78  void test_linked_list_at(void) {
    3.79 -    struct node {
    3.80 -        void *next;
    3.81 -        void *prev;
    3.82 -    };
    3.83 -    const ptrdiff_t loc_prev = offsetof(struct node, prev);
    3.84 -    const ptrdiff_t loc_next = offsetof(struct node, next);
    3.85 -
    3.86 -    struct node a, b, c, d;
    3.87 -    a.prev = NULL;
    3.88 -    a.next = &b;
    3.89 -    b.prev = &a;
    3.90 -    b.next = &c;
    3.91 -    c.prev = &b;
    3.92 -    c.next = &d;
    3.93 -    d.prev = &c;
    3.94 -    d.next = NULL;
    3.95 +    struct node nd(a), nd(b), nd(c), nd(d);
    3.96 +    cx_linked_list_link(&a, &b, loc_prev, loc_next);
    3.97 +    cx_linked_list_link(&b, &c, loc_prev, loc_next);
    3.98 +    cx_linked_list_link(&c, &d, loc_prev, loc_next);
    3.99  
   3.100      CU_ASSERT_PTR_EQUAL(cx_linked_list_at(&a, 0, loc_next, 0), &a)
   3.101      CU_ASSERT_PTR_EQUAL(cx_linked_list_at(&a, 0, loc_next, 1), &b)
   3.102 @@ -103,21 +125,43 @@
   3.103      CU_ASSERT_PTR_EQUAL(cx_linked_list_at(&d, 3, loc_prev, 1), &b)
   3.104  }
   3.105  
   3.106 +void test_linked_list_compare(void) {
   3.107 +    int a[] = {2, 4, 6, 8};
   3.108 +    int b[] = {2, 4, 6};
   3.109 +    int c[] = {2, 4, 6, 9};
   3.110 +
   3.111 +    void *la = create_test_data(4, a);
   3.112 +    void *lb = create_test_data(3, b);
   3.113 +    void *lc = create_test_data(4, c);
   3.114 +
   3.115 +    CU_ASSERT_TRUE(0 < cx_linked_list_compare(la, lb, loc_next, loc_data,
   3.116 +                                              0, (CxListComparator) cmp_int)
   3.117 +    )
   3.118 +    CU_ASSERT_TRUE(0 > cx_linked_list_compare(lb, la, loc_next, loc_data,
   3.119 +                                              0, (CxListComparator) cmp_int)
   3.120 +    )
   3.121 +    CU_ASSERT_TRUE(0 < cx_linked_list_compare(lc, la, loc_next, loc_data,
   3.122 +                                              0, (CxListComparator) cmp_int)
   3.123 +    )
   3.124 +    CU_ASSERT_TRUE(0 > cx_linked_list_compare(la, lc, loc_next, loc_data,
   3.125 +                                              0, (CxListComparator) cmp_int)
   3.126 +    )
   3.127 +    CU_ASSERT_TRUE(0 == cx_linked_list_compare(la, la, loc_next, loc_data,
   3.128 +                                               0, (CxListComparator) cmp_int)
   3.129 +    )
   3.130 +
   3.131 +    destroy_test_data(la);
   3.132 +    destroy_test_data(lb);
   3.133 +    destroy_test_data(lc);
   3.134 +}
   3.135 +
   3.136  void test_linked_list_add(void) {
   3.137 -    struct node {
   3.138 -        void *prev;
   3.139 -        void *next;
   3.140 -    };
   3.141 -
   3.142      struct node nodes[4];
   3.143 +    void *begin, *end;
   3.144  
   3.145      // test with begin, end / prev, next
   3.146      memset(nodes, 0, 4 * sizeof(struct node));
   3.147 -    void *begin = NULL;
   3.148 -    void *end = NULL;
   3.149 -
   3.150 -    ptrdiff_t loc_prev = offsetof(struct node, prev);
   3.151 -    ptrdiff_t loc_next = offsetof(struct node, next);
   3.152 +    begin = end = NULL;
   3.153  
   3.154      cx_linked_list_add(&begin, &end, loc_prev, loc_next, &nodes[0]);
   3.155      CU_ASSERT_PTR_EQUAL(begin, &nodes[0])
   3.156 @@ -133,8 +177,7 @@
   3.157  
   3.158      // test with begin only / prev, next
   3.159      memset(nodes, 0, 4 * sizeof(struct node));
   3.160 -    begin = NULL;
   3.161 -    end = NULL;
   3.162 +    begin = end = NULL;
   3.163  
   3.164      cx_linked_list_add(&begin, NULL, loc_prev, loc_next, &nodes[0]);
   3.165      CU_ASSERT_PTR_EQUAL(begin, &nodes[0])
   3.166 @@ -149,8 +192,7 @@
   3.167  
   3.168      // test with end only / prev, next
   3.169      memset(nodes, 0, 4 * sizeof(struct node));
   3.170 -    begin = NULL;
   3.171 -    end = NULL;
   3.172 +    begin = end = NULL;
   3.173  
   3.174      cx_linked_list_add(NULL, &end, loc_prev, loc_next, &nodes[0]);
   3.175      CU_ASSERT_PTR_EQUAL(end, &nodes[0])
   3.176 @@ -166,8 +208,7 @@
   3.177  
   3.178      // test with begin, end / next
   3.179      memset(nodes, 0, 4 * sizeof(struct node));
   3.180 -    begin = NULL;
   3.181 -    end = NULL;
   3.182 +    begin = end = NULL;
   3.183  
   3.184      cx_linked_list_add(&begin, &end, -1, loc_next, &nodes[0]);
   3.185      CU_ASSERT_PTR_EQUAL(begin, &nodes[0])
   3.186 @@ -179,20 +220,12 @@
   3.187  }
   3.188  
   3.189  void test_linked_list_prepend(void) {
   3.190 -    struct node {
   3.191 -        void *prev;
   3.192 -        void *next;
   3.193 -    };
   3.194 -
   3.195      struct node nodes[4];
   3.196 +    void *begin, *end;
   3.197  
   3.198      // test with begin, end / prev, next
   3.199      memset(nodes, 0, 4 * sizeof(struct node));
   3.200 -    void *begin = NULL;
   3.201 -    void *end = NULL;
   3.202 -
   3.203 -    ptrdiff_t loc_prev = offsetof(struct node, prev);
   3.204 -    ptrdiff_t loc_next = offsetof(struct node, next);
   3.205 +    begin = end = NULL;
   3.206  
   3.207      cx_linked_list_prepend(&begin, &end, loc_prev, loc_next, &nodes[0]);
   3.208      CU_ASSERT_PTR_EQUAL(begin, &nodes[0])
   3.209 @@ -208,8 +241,7 @@
   3.210  
   3.211      // test with begin only / prev, next
   3.212      memset(nodes, 0, 4 * sizeof(struct node));
   3.213 -    begin = NULL;
   3.214 -    end = NULL;
   3.215 +    begin = end = NULL;
   3.216  
   3.217      cx_linked_list_prepend(&begin, NULL, loc_prev, loc_next, &nodes[0]);
   3.218      CU_ASSERT_PTR_EQUAL(begin, &nodes[0])
   3.219 @@ -225,8 +257,7 @@
   3.220  
   3.221      // test with end only / prev, next
   3.222      memset(nodes, 0, 4 * sizeof(struct node));
   3.223 -    begin = NULL;
   3.224 -    end = NULL;
   3.225 +    begin = end = NULL;
   3.226  
   3.227      cx_linked_list_prepend(NULL, &end, loc_prev, loc_next, &nodes[0]);
   3.228      CU_ASSERT_PTR_EQUAL(end, &nodes[0])
   3.229 @@ -242,8 +273,7 @@
   3.230  
   3.231      // test with begin, end / next
   3.232      memset(nodes, 0, 4 * sizeof(struct node));
   3.233 -    begin = NULL;
   3.234 -    end = NULL;
   3.235 +    begin = end = NULL;
   3.236  
   3.237      cx_linked_list_prepend(&begin, &end, -1, loc_next, &nodes[0]);
   3.238      CU_ASSERT_PTR_EQUAL(begin, &nodes[0])
   3.239 @@ -259,13 +289,6 @@
   3.240  }
   3.241  
   3.242  void test_linked_list_insert(void) {
   3.243 -    struct node {
   3.244 -        void *prev;
   3.245 -        void *next;
   3.246 -    };
   3.247 -    ptrdiff_t loc_prev = offsetof(struct node, prev);
   3.248 -    ptrdiff_t loc_next = offsetof(struct node, next);
   3.249 -
   3.250      struct node nodes[4];
   3.251      void *begin, *end;
   3.252  
   3.253 @@ -317,13 +340,6 @@
   3.254  }
   3.255  
   3.256  void test_linked_list_insert_chain(void) {
   3.257 -    struct node {
   3.258 -        void *prev;
   3.259 -        void *next;
   3.260 -    };
   3.261 -    ptrdiff_t loc_prev = offsetof(struct node, prev);
   3.262 -    ptrdiff_t loc_next = offsetof(struct node, next);
   3.263 -
   3.264      struct node nodes[5];
   3.265      void *begin, *end;
   3.266  
   3.267 @@ -378,138 +394,78 @@
   3.268  }
   3.269  
   3.270  void test_linked_list_first(void) {
   3.271 -    struct node {
   3.272 -        int data;
   3.273 -        void *prev;
   3.274 -    };
   3.275 -    ptrdiff_t loc = offsetof(struct node, prev);
   3.276 -
   3.277 -    struct node first = {1, NULL};
   3.278 -    struct node second = {2, &first};
   3.279 -    struct node third = {3, &second};
   3.280 -
   3.281 -    CU_ASSERT_PTR_EQUAL(cx_linked_list_first(&first, loc), &first)
   3.282 -    CU_ASSERT_PTR_EQUAL(cx_linked_list_first(&second, loc), &first)
   3.283 -    CU_ASSERT_PTR_EQUAL(cx_linked_list_first(&third, loc), &first)
   3.284 +    struct node *begin = create_test_data(3, NULL);
   3.285 +    CU_ASSERT_PTR_EQUAL(cx_linked_list_first(begin, loc_prev), begin)
   3.286 +    CU_ASSERT_PTR_EQUAL(cx_linked_list_first(begin->next, loc_prev), begin)
   3.287 +    CU_ASSERT_PTR_EQUAL(cx_linked_list_first(begin->next->next, loc_prev), begin)
   3.288 +    destroy_test_data(begin);
   3.289  }
   3.290  
   3.291  void test_linked_list_last(void) {
   3.292 -    struct node {
   3.293 -        int data;
   3.294 -        void *next;
   3.295 -    };
   3.296 -    ptrdiff_t loc = offsetof(struct node, next);
   3.297 -
   3.298 -    struct node third = {3, NULL};
   3.299 -    struct node second = {2, &third};
   3.300 -    struct node first = {1, &second};
   3.301 -
   3.302 -    CU_ASSERT_PTR_EQUAL(cx_linked_list_last(&first, loc), &third)
   3.303 -    CU_ASSERT_PTR_EQUAL(cx_linked_list_last(&second, loc), &third)
   3.304 -    CU_ASSERT_PTR_EQUAL(cx_linked_list_last(&third, loc), &third)
   3.305 +    struct node *begin = create_test_data(3, NULL);
   3.306 +    struct node *end = begin->next->next;
   3.307 +    CU_ASSERT_PTR_EQUAL(cx_linked_list_last(begin, loc_next), end)
   3.308 +    CU_ASSERT_PTR_EQUAL(cx_linked_list_last(begin->next, loc_next), end)
   3.309 +    CU_ASSERT_PTR_EQUAL(cx_linked_list_last(begin->next->next, loc_next), end)
   3.310 +    destroy_test_data(begin);
   3.311  }
   3.312  
   3.313  void test_linked_list_prev(void) {
   3.314 -    struct node {
   3.315 -        void *next;
   3.316 -    };
   3.317 -    ptrdiff_t loc = offsetof(struct node, next);
   3.318 -
   3.319 -    struct node third = {NULL};
   3.320 -    struct node second = {&third};
   3.321 -    struct node first = {&second};
   3.322 -
   3.323 -    CU_ASSERT_PTR_NULL(cx_linked_list_prev(&first, loc, &first))
   3.324 -    CU_ASSERT_PTR_EQUAL(cx_linked_list_prev(&first, loc, &second), &first)
   3.325 -    CU_ASSERT_PTR_EQUAL(cx_linked_list_prev(&first, loc, &third), &second)
   3.326 +    struct node *begin = create_test_data(3, NULL);
   3.327 +    CU_ASSERT_PTR_NULL(cx_linked_list_prev(begin, loc_next, begin))
   3.328 +    CU_ASSERT_PTR_EQUAL(cx_linked_list_prev(begin, loc_next, begin->next), begin)
   3.329 +    CU_ASSERT_PTR_EQUAL(cx_linked_list_prev(begin, loc_next, begin->next->next), begin->next)
   3.330 +    destroy_test_data(begin);
   3.331  }
   3.332  
   3.333  void test_linked_list_remove(void) {
   3.334 -    struct node {
   3.335 -        void *next;
   3.336 -    };
   3.337 -    struct dnode {
   3.338 -        void *next;
   3.339 -        void *prev;
   3.340 -    };
   3.341 -    ptrdiff_t loc = offsetof(struct node, next);
   3.342 -    ptrdiff_t ploc = offsetof(struct dnode, prev);
   3.343 +    void *begin, *end;
   3.344  
   3.345 -    void *begin;
   3.346 -    void *end;
   3.347 +    int data[] = {2, 4, 6};
   3.348 +    begin = create_test_data(3, data);
   3.349 +    struct node *first = begin;
   3.350 +    struct node *second = first->next;
   3.351 +    struct node *third = second->next;
   3.352 +    end = third;
   3.353  
   3.354 -    // single linked list
   3.355 -    struct node third = {NULL};
   3.356 -    struct node second = {&third};
   3.357 -    struct node first = {&second};
   3.358 -    begin = &first;
   3.359 +    cx_linked_list_remove(&begin, &end, loc_prev, loc_next, second);
   3.360 +    CU_ASSERT_PTR_EQUAL(begin, first)
   3.361 +    CU_ASSERT_PTR_EQUAL(end, third)
   3.362 +    CU_ASSERT_PTR_NULL(first->prev)
   3.363 +    CU_ASSERT_PTR_EQUAL(first->next, third)
   3.364 +    CU_ASSERT_PTR_EQUAL(third->prev, first)
   3.365 +    CU_ASSERT_PTR_NULL(third->next)
   3.366  
   3.367 -    cx_linked_list_remove(&begin, NULL, -1, loc, &second);
   3.368 -    CU_ASSERT_PTR_EQUAL(begin, &first)
   3.369 -    CU_ASSERT_PTR_EQUAL(first.next, &third)
   3.370 -    CU_ASSERT_PTR_NULL(third.next)
   3.371 +    cx_linked_list_remove(&begin, &end, loc_prev, loc_next, third);
   3.372 +    CU_ASSERT_PTR_EQUAL(begin, first)
   3.373 +    CU_ASSERT_PTR_EQUAL(end, first)
   3.374 +    CU_ASSERT_PTR_NULL(first->prev)
   3.375 +    CU_ASSERT_PTR_NULL(first->next)
   3.376  
   3.377 -    cx_linked_list_remove(&begin, NULL, -1, loc, &first);
   3.378 -    CU_ASSERT_PTR_EQUAL(begin, &third)
   3.379 -    CU_ASSERT_PTR_NULL(third.next)
   3.380 -
   3.381 -    cx_linked_list_remove(&begin, NULL, -1, loc, &third);
   3.382 -    CU_ASSERT_PTR_NULL(begin)
   3.383 -
   3.384 -    // doubly linked list
   3.385 -    struct dnode dthird = {NULL , NULL};
   3.386 -    struct dnode dsecond = {&dthird, NULL};
   3.387 -    struct dnode dfirst = {&dsecond, NULL};
   3.388 -    dthird.prev = &dsecond;
   3.389 -    dsecond.prev = &dfirst;
   3.390 -    begin = &dfirst;
   3.391 -    end = &dthird;
   3.392 -
   3.393 -    cx_linked_list_remove(&begin, &end, ploc, loc, &dsecond);
   3.394 -    CU_ASSERT_PTR_EQUAL(begin, &dfirst)
   3.395 -    CU_ASSERT_PTR_EQUAL(end, &dthird)
   3.396 -    CU_ASSERT_PTR_NULL(dfirst.prev)
   3.397 -    CU_ASSERT_PTR_EQUAL(dfirst.next, &dthird)
   3.398 -    CU_ASSERT_PTR_EQUAL(dthird.prev, &dfirst)
   3.399 -    CU_ASSERT_PTR_NULL(dthird.next)
   3.400 -
   3.401 -    cx_linked_list_remove(&begin, &end, ploc, loc, &dthird);
   3.402 -    CU_ASSERT_PTR_EQUAL(begin, &dfirst)
   3.403 -    CU_ASSERT_PTR_EQUAL(end, &dfirst)
   3.404 -    CU_ASSERT_PTR_NULL(dfirst.prev)
   3.405 -    CU_ASSERT_PTR_NULL(dfirst.next)
   3.406 -
   3.407 -    cx_linked_list_remove(&begin, &end, ploc, loc, &dfirst);
   3.408 +    cx_linked_list_remove(&begin, &end, loc_prev, loc_next, first);
   3.409      CU_ASSERT_PTR_NULL(begin)
   3.410      CU_ASSERT_PTR_NULL(end)
   3.411 +
   3.412 +    free(first);
   3.413 +    free(second);
   3.414 +    free(third);
   3.415  }
   3.416  
   3.417  void test_linked_list_size(void) {
   3.418 -    struct node {
   3.419 -        void *next;
   3.420 -    };
   3.421 -    ptrdiff_t loc = offsetof(struct node, next);
   3.422 +    struct node *list;
   3.423  
   3.424 -    struct node first = {NULL};
   3.425 -    struct node second = {NULL};
   3.426 -    struct node third = {NULL};
   3.427 +    CU_ASSERT_PTR_EQUAL(cx_linked_list_size(NULL, loc_next), 0)
   3.428  
   3.429 -    CU_ASSERT_PTR_EQUAL(cx_linked_list_size(NULL, loc), 0)
   3.430 -    CU_ASSERT_PTR_EQUAL(cx_linked_list_size(&first, loc), 1)
   3.431 -    first.next = &second;
   3.432 -    CU_ASSERT_PTR_EQUAL(cx_linked_list_size(&first, loc), 2)
   3.433 -    second.next = &third;
   3.434 -    CU_ASSERT_PTR_EQUAL(cx_linked_list_size(&first, loc), 3)
   3.435 -    CU_ASSERT_PTR_EQUAL(cx_linked_list_size(&second, loc), 2)
   3.436 +    list = create_test_data(5, NULL);
   3.437 +    CU_ASSERT_EQUAL(cx_linked_list_size(list, loc_next), 5)
   3.438 +    destroy_test_data(list);
   3.439 +
   3.440 +    list = create_test_data(13, NULL);
   3.441 +    CU_ASSERT_EQUAL(cx_linked_list_size(list, loc_next), 13)
   3.442 +    destroy_test_data(list);
   3.443  }
   3.444  
   3.445  void test_linked_list_sort(void) {
   3.446 -    struct node {
   3.447 -        void *prev;
   3.448 -        void *next;
   3.449 -        int data;
   3.450 -    };
   3.451 -
   3.452      int expected[] = {
   3.453              14, 30, 151, 163, 227, 300, 315, 317, 363, 398, 417, 424, 438, 446, 508, 555, 605, 713, 716, 759, 761, 880,
   3.454              894, 1034, 1077, 1191, 1231, 1264, 1297, 1409, 1423, 1511, 1544, 1659, 1686, 1707, 1734, 1771, 1874, 1894,
   3.455 @@ -527,26 +483,16 @@
   3.456              4016, 4085, 4121, 4254, 4319, 4366, 4459, 4514, 4681
   3.457      };
   3.458  
   3.459 -    struct node *nodes = calloc(100, sizeof(struct node));
   3.460 -    for (int i = 0; i < 100; i++) {
   3.461 -        nodes[i].prev = i == 0 ? NULL : &nodes[i - 1];
   3.462 -        nodes[i].next = i == 99 ? NULL : &nodes[i + 1];
   3.463 -        nodes[i].data = scrambled[i];
   3.464 -    }
   3.465 +    void *begin = create_test_data(100, scrambled);
   3.466 +    void *end = cx_linked_list_last(begin, loc_next);
   3.467  
   3.468 -    struct node *begin = &nodes[0];
   3.469 -    struct node *end = &nodes[99];
   3.470 -
   3.471 -    cx_linked_list_sort((void **) &begin, (void **) &end,
   3.472 -                        offsetof(struct node, prev),
   3.473 -                        offsetof(struct node, next),
   3.474 -                        offsetof(struct node, data),
   3.475 +    cx_linked_list_sort(&begin, &end, loc_prev, loc_next, loc_data,
   3.476                          0, (CxListComparator) cmp_int);
   3.477  
   3.478 -    CU_ASSERT_PTR_NULL(begin->prev)
   3.479 -    CU_ASSERT_EQUAL(begin->data, expected[0])
   3.480      struct node *check = begin;
   3.481      struct node *check_last = NULL;
   3.482 +    CU_ASSERT_PTR_NULL(check->prev)
   3.483 +    CU_ASSERT_EQUAL(check->data, expected[0])
   3.484      for (int i = 0; i < 100; i++) {
   3.485          CU_ASSERT_EQUAL(check->data, expected[i])
   3.486          CU_ASSERT_PTR_EQUAL(check->prev, check_last)
   3.487 @@ -557,53 +503,31 @@
   3.488          check = check->next;
   3.489      }
   3.490      CU_ASSERT_PTR_NULL(check)
   3.491 -    CU_ASSERT_EQUAL(end->data, expected[99])
   3.492 +    CU_ASSERT_PTR_EQUAL(end, check_last)
   3.493 +
   3.494 +    destroy_test_data(begin);
   3.495  }
   3.496  
   3.497  void test_linked_list_reverse(void) {
   3.498 -    struct node {
   3.499 -        void *next;
   3.500 -    };
   3.501 -    struct dnode {
   3.502 -        void *next;
   3.503 -        void *prev;
   3.504 -    };
   3.505 -    ptrdiff_t loc = offsetof(struct node, next);
   3.506 -    ptrdiff_t ploc = offsetof(struct dnode, prev);
   3.507 +    void *begin, *end;
   3.508  
   3.509 -    void *begin;
   3.510 -    void *end;
   3.511 +    int data[] = {2, 4, 6, 8};
   3.512 +    int reversed[] = {8, 6, 4, 2};
   3.513  
   3.514 -    // single linked list
   3.515 -    struct node third = {NULL};
   3.516 -    struct node second = {&third};
   3.517 -    struct node first = {&second};
   3.518 -    begin = &first;
   3.519 +    void *list = create_test_data(4, data);
   3.520 +    void *expected = create_test_data(4, reversed);
   3.521  
   3.522 -    cx_linked_list_reverse(&begin, NULL, -1, loc);
   3.523 -    CU_ASSERT_PTR_EQUAL(begin, &third)
   3.524 -    CU_ASSERT_PTR_EQUAL(third.next, &second)
   3.525 -    CU_ASSERT_PTR_EQUAL(second.next, &first)
   3.526 -    CU_ASSERT_PTR_NULL(first.next)
   3.527 +    begin = list;
   3.528 +    end = cx_linked_list_last(list, loc_next);
   3.529  
   3.530 -    // doubly linked list
   3.531 -    struct dnode dthird = {NULL , NULL};
   3.532 -    struct dnode dsecond = {&dthird, NULL};
   3.533 -    struct dnode dfirst = {&dsecond, NULL};
   3.534 -    dthird.prev = &dsecond;
   3.535 -    dsecond.prev = &dfirst;
   3.536 -    begin = &dfirst;
   3.537 -    end = &dthird;
   3.538 +    cx_linked_list_reverse(&begin, &end, loc_prev, loc_next);
   3.539 +    CU_ASSERT_PTR_EQUAL(end, list)
   3.540 +    CU_ASSERT_PTR_EQUAL(begin, cx_linked_list_first(end, loc_prev))
   3.541 +    CU_ASSERT_TRUE(0 == cx_linked_list_compare(begin, expected, loc_next, loc_data,
   3.542 +                                               0, (CxListComparator) cmp_int))
   3.543  
   3.544 -    cx_linked_list_reverse(&begin, &end, ploc, loc);
   3.545 -    CU_ASSERT_PTR_EQUAL(begin, &dthird)
   3.546 -    CU_ASSERT_PTR_EQUAL(end, &dfirst)
   3.547 -    CU_ASSERT_PTR_EQUAL(dthird.next, &dsecond)
   3.548 -    CU_ASSERT_PTR_EQUAL(dsecond.next, &dfirst)
   3.549 -    CU_ASSERT_PTR_NULL(dfirst.next)
   3.550 -    CU_ASSERT_PTR_NULL(dthird.prev)
   3.551 -    CU_ASSERT_PTR_EQUAL(dsecond.prev, &dthird)
   3.552 -    CU_ASSERT_PTR_EQUAL(dfirst.prev, &dsecond)
   3.553 +    destroy_test_data(begin);
   3.554 +    destroy_test_data(expected);
   3.555  }
   3.556  
   3.557  void test_hl_linked_list_create(void) {
   3.558 @@ -1028,6 +952,7 @@
   3.559  
   3.560      cu_add_test(suite, test_linked_list_link_unlink);
   3.561      cu_add_test(suite, test_linked_list_at);
   3.562 +    cu_add_test(suite, test_linked_list_compare);
   3.563      cu_add_test(suite, test_linked_list_prepend);
   3.564      cu_add_test(suite, test_linked_list_add);
   3.565      cu_add_test(suite, test_linked_list_insert);

mercurial