alist: Add a way to efficiently filter an alist

Unlike linked lists, it is inefficient to remove items from an alist,
particularly if it is large. If most items need to be removed, then the
time-complexity approaches O(n2).

Provide a way to do this efficiently, by working through the alist once
and copying elements down.

Signed-off-by: Simon Glass <sjg@chromium.org>
This commit is contained in:
Simon Glass
2024-10-19 09:21:47 -06:00
committed by Tom Rini
parent 5bd4ead8bd
commit 5dfc1c8078
3 changed files with 123 additions and 0 deletions

View File

@@ -274,6 +274,36 @@ bool alist_chk_ptr(const struct alist *lst, const void *ptr);
_pos < alist_end(_lst, typeof(*(_pos))); \
_pos++)
/**
* alist_for_each_filter() - version which sets up a 'from' pointer too
*
* This is used for filtering out information in the list. It works by iterating
* through the list, copying elements down over the top of elements to be
* deleted.
*
* In this example, 'from' iterates through the list from start to end,, 'to'
* also begins at the start, but only increments if the element at 'from' should
* be kept. This provides an O(n) filtering operation. Note that
* alist_update_end() must be called after the loop, to update the count.
*
* alist_for_each_filter(from, to, &lst) {
* if (from->val != 2)
* *to++ = *from;
* }
* alist_update_end(&lst, to);
*/
#define alist_for_each_filter(_pos, _from, _lst) \
for (_pos = _from = alist_start(_lst, typeof(*(_pos))); \
_pos < alist_end(_lst, typeof(*(_pos))); \
_pos++)
/**
* alist_update_end() - Set the element count based on a given pointer
*
* Set the given element as the final one
*/
void alist_update_end(struct alist *lst, const void *end);
/**
* alist_empty() - Empty an alist
*