8static void * __cstl_dlist_element(
const struct cstl_dlist *
const l,
11 return (
void *)((uintptr_t)n - l->off);
19 return (
void *)((uintptr_t)e + l->off);
37static void __cstl_dlist_insert(
struct cstl_dlist *
const l,
53 void *
const pe,
void *
const e)
55 __cstl_dlist_insert(l, __cstl_dlist_node(l, pe), __cstl_dlist_node(l, e));
59static void * __cstl_dlist_erase(
struct cstl_dlist *
const l,
67 return __cstl_dlist_element(l, n);
72 __cstl_dlist_erase(l, __cstl_dlist_node(l, e));
78 return __cstl_dlist_element(l, l->h.n);
86 return __cstl_dlist_element(l, l->h.p);
93 __cstl_dlist_insert(l, &l->h, __cstl_dlist_node(l, e));
98 __cstl_dlist_insert(l, l->h.p, __cstl_dlist_node(l, e));
104 return __cstl_dlist_erase(l, l->h.n);
112 return __cstl_dlist_erase(l, l->h.p);
128 next = __cstl_dlist_next;
131 next = __cstl_dlist_prev;
135 for (c = *next(&l->h), n = *next(c);
136 res == 0 && c != &l->h;
137 c = n, n = *next(c)) {
138 res = visit(__cstl_dlist_element(l, c), p);
145struct cstl_dlist_find_priv
153static int cstl_dlist_find_visit(
void *
const e,
void *
const p)
155 struct cstl_dlist_find_priv * lfp = p;
157 if (lfp->cmp(lfp->e, e, lfp->p) == 0) {
166 const void *
const e,
170 struct cstl_dlist_find_priv lfp;
177 cstl_dlist_find_visit, &lfp, dir) > 0) {
178 return (
void *)lfp.e;
191#define CSTL_DLIST_SWAP_FIX(L) \
193 if (L->size == 0) { \
194 L->h.n = L->h.p = &L->h; \
196 L->h.n->p = L->h.p->n = &L->h; \
200 CSTL_DLIST_SWAP_FIX(a);
201 CSTL_DLIST_SWAP_FIX(b);
203#undef CSTL_DLIST_SWAP_FIX
210 while (l->size > 0) {
211 clr(__cstl_dlist_erase(l, l->h.n), NULL);
232 for (i = l->h.n, j = l->h.p;
234 k = i->p, i = j->n, j = k) {
274 if (d != s && d->off == s->off && s->size > 0) {
311 _l[0].size < l->size / 2;
312 t = t->n, _l[0].size++)
321 _l[0].h.n->p = _l[0].h.p->n = &_l[0].h;
322 _l[1].h.n->p = _l[1].h.p->n = &_l[1].h;
324 _l[1].size = l->size - _l[0].size;
336 while (_l[0].size > 0 && _l[1].size > 0) {
340 if (cmp(__cstl_dlist_element(&_l[0], _l[0].h.n),
341 __cstl_dlist_element(&_l[1], _l[1].h.n),
349 __cstl_dlist_erase(ol, n);
350 __cstl_dlist_insert(l, l->h.p, n);
354 if (_l[0].size > 0) {
373static int cmp_integer(
const void *
const a,
const void *
const b,
377 return ((
struct integer *)a)->v - ((
struct integer *)b)->v;
380static void __test_cstl_dlist_free(
void *
const p,
void *
const x)
386static void __test__cstl_dlist_fill(
struct cstl_dlist * l,
const size_t n)
390 for (i = 0; i < n; i++) {
391 struct integer * in = malloc(
sizeof(*in));
403 struct integer a, b, c;
405 a.v = 0; b.v = 1; c.v = 2;
428 &b, cmp_integer, NULL,
437 &a, cmp_integer, NULL,
452 static const size_t n = 100;
455 __test__cstl_dlist_fill(&l, n);
464 static const size_t n = 4;
468 __test__cstl_dlist_fill(&l1, n);
469 __test__cstl_dlist_fill(&l2, n);
480static int cstl_dlist_verify_sorted_fwd(
void *
const e,
void *
const p)
482 struct integer ** in = p;
484 ck_assert_int_ge(((
struct integer *)e)->v, (*in)->v);
490static int cstl_dlist_verify_sorted_rev(
void *
const e,
void *
const p)
492 struct integer ** in = p;
494 ck_assert_int_le(((
struct integer *)e)->v, (*in)->v);
502 static const size_t n = 100;
507 __test__cstl_dlist_fill(&l, n);
513 cstl_dlist_verify_sorted_fwd, &in,
517 cstl_dlist_verify_sorted_rev, &in,
527 static const size_t n = 100;
530 struct integer * in = NULL;
532 __test__cstl_dlist_fill(&l, n);
537 cstl_dlist_verify_sorted_rev, &in,
550 __test__cstl_dlist_fill(&l1, 0);
557 __test__cstl_dlist_fill(&l1, 1);
564 __test__cstl_dlist_fill(&l1, 2);
571 __test__cstl_dlist_fill(&l1, 2);
572 __test__cstl_dlist_fill(&l2, 3);
581Suite * dlist_suite(
void)
583 Suite *
const s = suite_create(
"dlist");
587 tc = tcase_create(
"dlist");
588 tcase_add_test(tc, simple);
589 tcase_add_test(tc, fill);
590 tcase_add_test(tc, concat);
591 tcase_add_test(tc, sort);
592 tcase_add_test(tc, reverse);
593 tcase_add_test(tc, swap);
594 suite_add_tcase(s, tc);
static void cstl_swap(void *const x, void *const y, void *const t, const size_t sz)
Swap values at two memory locations via use of a third.
void cstl_xtor_func_t(void *obj, void *priv)
Type for functions called to construct, clear, or destroy an object.
int cstl_visit_func_t(void *obj, void *priv)
Type for visit callbacks from objects supporting foreach.
int cstl_compare_func_t(const void *obj1, const void *obj2, void *priv)
Function type for comparing (in)equality of two objects.
#define DECLARE_CSTL_DLIST(NAME, TYPE, MEMB)
(Statically) declare and initialize a list
static void cstl_dlist_init(struct cstl_dlist *const l, const size_t off)
Initialize a list object.
void * cstl_dlist_front(struct cstl_dlist *const l)
Get a pointer to the first object in the list.
void cstl_dlist_reverse(struct cstl_dlist *const l)
Reverse the order of items in the list.
void cstl_dlist_clear(struct cstl_dlist *const l, cstl_xtor_func_t *const clr)
Remove objects from and reinitialize a list.
void * cstl_dlist_pop_front(struct cstl_dlist *const l)
Remove the first item in the list and return it.
void cstl_dlist_erase(struct cstl_dlist *const l, void *const e)
Remove an object from the list.
static size_t cstl_dlist_size(const struct cstl_dlist *const l)
Get the number of objects in the list.
void cstl_dlist_swap(struct cstl_dlist *const a, struct cstl_dlist *const b)
Swap the list objects at the two given locations.
void cstl_dlist_concat(struct cstl_dlist *const d, struct cstl_dlist *const s)
Append one list to the end of another.
void * cstl_dlist_find(const struct cstl_dlist *const l, const void *const e, cstl_compare_func_t *const cmp, void *const cmp_p, const cstl_dlist_foreach_dir_t dir)
Perform a linear search for an object.
void * cstl_dlist_pop_back(struct cstl_dlist *const l)
Remove the last item in the list and return it.
void cstl_dlist_push_front(struct cstl_dlist *const l, void *const e)
Insert a new object at the front of the list.
cstl_dlist_foreach_dir_t
The direction in which to traverse the list during cstl_dlist_foreach()
void cstl_dlist_push_back(struct cstl_dlist *const l, void *const e)
Insert a new object at the back of the list.
int cstl_dlist_foreach(struct cstl_dlist *const l, cstl_visit_func_t *const visit, void *const p, const cstl_dlist_foreach_dir_t dir)
Call a user-supplied function for each object in a list.
void * cstl_dlist_back(struct cstl_dlist *const l)
Get a pointer to the last object in the list.
void cstl_dlist_sort(struct cstl_dlist *const l, cstl_compare_func_t *const cmp, void *const priv)
Sort the items in a list.
void cstl_dlist_insert(struct cstl_dlist *const l, void *const pe, void *const e)
Insert a new object into the list.
@ CSTL_DLIST_FOREACH_DIR_FWD
Traverse the list from front to back.
@ CSTL_DLIST_FOREACH_DIR_REV
Traverse the list from back to front.
Node to anchor an element within a list.