commonlib/list: Add list_length() and more to API

In a follow-up patch (CB:90962), the list will be changed to a circular
one, and list_node fields 'next' and 'prev' will become private to the
implementation.

To allow smooth transition to circular lists for all call sites, add the
following functions to the list API:

- list_is_empty()
- list_next()
- list_prev()
- list_first()
- list_last()
- list_length()

All list API call sites are expected to use the public API instead of
the raw 'next' and 'prev' pointers.

Change-Id: Ib1040f5caab8550ea52db9b55a074d7d79c591e5
Signed-off-by: Yu-Ping Wu <yupingso@google.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/90961
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Jakub "Kuba" Czapiga <czapiga@google.com>
Reviewed-by: Julius Werner <jwerner@chromium.org>
This commit is contained in:
Yu-Ping Wu 2026-01-28 12:30:50 +08:00 committed by Matt DeVillier
commit e50f7e8b49
3 changed files with 120 additions and 37 deletions

View file

@ -5,6 +5,7 @@
#define __COMMONLIB_LIST_H__
#include <commonlib/helpers.h>
#include <stdbool.h>
#include <stdint.h>
struct list_node {
@ -18,9 +19,41 @@ void list_remove(struct list_node *node);
void list_insert_after(struct list_node *node, struct list_node *after);
// Insert list_node node before list_node before in a doubly linked list.
void list_insert_before(struct list_node *node, struct list_node *before);
// Appends the node to the end of the list.
// Append the node to the end of the list.
void list_append(struct list_node *node, struct list_node *head);
// Return if the list is empty.
static inline bool list_is_empty(const struct list_node *head)
{
return !head->next;
}
// Get next node.
static inline const struct list_node *list_next(const struct list_node *node,
const struct list_node *head)
{
return node->next;
};
// Get prev node.
static inline const struct list_node *list_prev(const struct list_node *node,
const struct list_node *head)
{
return node->prev == head ? NULL : node->prev;
};
// Get first node.
static inline const struct list_node *list_first(const struct list_node *head)
{
return list_is_empty(head) ? NULL : head->next;
}
// Get last node.
const struct list_node *list_last(const struct list_node *head);
// Get the number of list elements.
size_t list_length(const struct list_node *head);
#define list_for_each(ptr, head, member) \
for ((ptr) = container_of((head).next, typeof(*(ptr)), member); \
(uintptr_t)ptr + (uintptr_t)offsetof(typeof(*(ptr)), member); \

View file

@ -36,3 +36,24 @@ void list_append(struct list_node *node, struct list_node *head)
list_insert_after(node, head);
}
const struct list_node *list_last(const struct list_node *head)
{
const struct list_node *ptr = head;
while (ptr->next)
ptr = ptr->next;
return ptr == head ? NULL : ptr;
}
size_t list_length(const struct list_node *head)
{
struct {
struct list_node node;
} const *ptr;
size_t len = 0;
list_for_each(ptr, *head, node)
len++;
return len;
}