From 760e17f142eb5cc0f594f1383ae68bb63bebe9ee Mon Sep 17 00:00:00 2001 From: Dimitri Staessens Date: Sun, 15 Feb 2026 12:26:04 +0100 Subject: lib: Add struct llist for lists tracking len The DHT uses a struct {struct list_head, size_t len} pattern, which is also useful in the registry and other places. Having a struct llist (defined in list.h) with consistent macros for addition/deletion etc removes a lot of duplication and boilerplate and reduces the risk of inconsistent updates. The list management is now a macro-only implementation. Signed-off-by: Dimitri Staessens Signed-off-by: Sander Vrijders --- include/ouroboros/list.h | 93 +++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 84 insertions(+), 9 deletions(-) (limited to 'include') diff --git a/include/ouroboros/list.h b/include/ouroboros/list.h index a00cfe61..26138b28 100644 --- a/include/ouroboros/list.h +++ b/include/ouroboros/list.h @@ -33,6 +33,11 @@ struct list_head { struct list_head * prv; }; +struct llist { + struct list_head list; + size_t len; +}; + #define list_entry(ptr, type, mbr) \ ((type *)((uint8_t *)(ptr) - offsetof(type, mbr))) @@ -48,19 +53,89 @@ struct list_head { #define list_for_each_safe(p, t, h) \ for (p = (h)->nxt, t = p->nxt; p != (h); p = t, t = p->nxt) -void list_head_init(struct list_head * h); +#define list_head_init(h) do { \ + (h)->nxt = (h); \ + (h)->prv = (h); \ +} while (0) + +#define __list_add(_n, _prv, _nxt) do { \ + struct list_head * __nxt = (_nxt); \ + struct list_head * __prv = (_prv); \ + struct list_head * __n = (_n); \ + __nxt->prv = __n; \ + __n->nxt = __nxt; \ + __n->prv = __prv; \ + __prv->nxt = __n; \ +} while (0) + +#define __list_del(_prv, _nxt) do { \ + struct list_head * __nxt = (_nxt); \ + struct list_head * __prv = (_prv); \ + __nxt->prv = __prv; \ + __prv->nxt = __nxt; \ +} while (0) + +#define list_add(n, h) do { \ + __list_add(n, h, (h)->nxt); \ +} while (0) + +#define list_add_tail(n, h) do { \ + __list_add(n, (h)->prv, h); \ +} while (0) + +#define list_del(e) do { \ + __list_del((e)->prv, (e)->nxt); \ + (e)->nxt = (e)->prv = (e); \ +} while (0) + +#define list_move(n, h) do { \ + __list_del((n)->prv, (n)->nxt); \ + __list_add(n, h, (h)->nxt); \ +} while (0) + +#define list_is_empty(h) ((h)->nxt == (h)) + +#define llist_init(l) do { \ + list_head_init(&(l)->list); \ + (l)->len = 0; \ +} while (0) + +#define llist_add(e, l) do { \ + list_add(e, &(l)->list); \ + (l)->len++; \ +} while (0) + +#define llist_add_tail(e, l) do { \ + list_add_tail(e, &(l)->list); \ + (l)->len++; \ +} while (0) + +#define llist_add_at(e, pos, l) do { \ + list_add(e, pos); \ + (l)->len++; \ +} while (0) + +#define llist_add_tail_at(e, pos, l) do { \ + list_add_tail(e, pos); \ + (l)->len++; \ +} while (0) + +#define llist_del(e, l) do { \ + list_del(e); \ + (l)->len--; \ +} while (0) -void list_add(struct list_head * e, - struct list_head * h); +#define llist_is_empty(l) ((l)->len == 0) -void list_add_tail(struct list_head * e, - struct list_head * h); +#define llist_first_entry(l, type, mbr) \ + list_first_entry(&(l)->list, type, mbr) -void list_del(struct list_head * e); +#define llist_last_entry(l, type, mbr) \ + list_last_entry(&(l)->list, type, mbr) -void list_move(struct list_head * dst, - struct list_head * src); +#define llist_for_each(p, l) list_for_each(p, &(l)->list) -bool list_is_empty(const struct list_head * h); +#define llist_for_each_safe(p, t, l) \ + list_for_each_safe(p, t, &(l)->list) #endif /* OUROBOROS_LIB_LIST_H */ -- cgit v1.2.3