[PATCH 05/34] alist: Add for-loop helpers
Simon Glass
sjg at chromium.org
Fri Oct 18 01:23:44 CEST 2024
Add some macros which permit easy iteration through an alist, similar to
those provided by the 'list' implementation.
Signed-off-by: Simon Glass <sjg at chromium.org>
---
include/alist.h | 50 ++++++++++++++++++++++++++++++++
lib/alist.c | 7 +++++
test/lib/alist.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 131 insertions(+)
diff --git a/include/alist.h b/include/alist.h
index 97523af37a6..0090b9c0eb1 100644
--- a/include/alist.h
+++ b/include/alist.h
@@ -224,6 +224,56 @@ bool alist_expand_by(struct alist *lst, uint inc_by);
*/
const void *alist_next_ptrd(const struct alist *lst, const void *ptr);
+/**
+ * alist_chk_ptr() - Check whether a pointer is within a list
+ *
+ * Checks if the pointer points to an existing element of the list. The pointer
+ * must point to the start of an element, either in the list, or just outside of
+ * it. This function is only useful for handling for() loops
+ *
+ * Return: true if @ptr is within the list (0..count-1), else false
+ */
+bool alist_chk_ptr(const struct alist *lst, const void *ptr);
+
+/**
+ * alist_start() - Get the start of the list (first element)
+ *
+ * Note that this will always return ->data even if it is not NULL
+ *
+ * Usage:
+ * const struct my_struct *obj; # 'const' is optional
+ *
+ * alist_start(&lst, struct my_struct)
+ */
+#define alist_start(_lst, _struct) \
+ ((_struct *)(_lst)->data)
+
+/**
+ * alist_end() - Get the end of the list (just after last element)
+ *
+ * Usage:
+ * const struct my_struct *obj; # 'const' is optional
+ *
+ * alist_end(&lst, struct my_struct)
+ */
+#define alist_end(_lst, _struct) \
+ ((_struct *)(_lst)->data + (_lst)->count)
+
+/**
+ * alist_for_each() - Iterate over an alist (with constant pointer)
+ *
+ * Use as:
+ * const struct my_struct *obj; # 'const' is optional
+ *
+ * alist_for_each(obj, &lst) {
+ * obj->...
+ * }
+ */
+#define alist_for_each(_pos, _lst) \
+ for (_pos = alist_start(_lst, typeof(*(_pos))); \
+ _pos < alist_end(_lst, typeof(*(_pos))); \
+ _pos++)
+
/**
* alist_init() - Set up a new object list
*
diff --git a/lib/alist.c b/lib/alist.c
index 7730fe0d473..1a4b4fb9c40 100644
--- a/lib/alist.c
+++ b/lib/alist.c
@@ -118,6 +118,13 @@ int alist_calc_index(const struct alist *lst, const void *ptr)
return index;
}
+bool alist_chk_ptr(const struct alist *lst, const void *ptr)
+{
+ int index = alist_calc_index(lst, ptr);
+
+ return index >= 0 && index < lst->count;
+}
+
const void *alist_next_ptrd(const struct alist *lst, const void *ptr)
{
int index = alist_calc_index(lst, ptr);
diff --git a/test/lib/alist.c b/test/lib/alist.c
index 96092affec9..1715a22584c 100644
--- a/test/lib/alist.c
+++ b/test/lib/alist.c
@@ -292,3 +292,77 @@ static int lib_test_alist_next(struct unit_test_state *uts)
return 0;
}
LIB_TEST(lib_test_alist_next, 0);
+
+/* Test alist_for_each() */
+static int lib_test_alist_for_each(struct unit_test_state *uts)
+{
+ const struct my_struct *ptr;
+ struct my_struct data, *ptr2;
+ struct alist lst;
+ ulong start;
+ int sum;
+
+ start = ut_check_free();
+
+ ut_assert(alist_init_struct(&lst, struct my_struct));
+ ut_asserteq_ptr(NULL, alist_end(&lst, struct my_struct));
+
+ sum = 0;
+ alist_for_each(ptr, &lst)
+ sum++;
+ ut_asserteq(0, sum);
+
+ alist_for_each(ptr, &lst)
+ sum++;
+ ut_asserteq(0, sum);
+
+ /* add three items */
+ data.val = 1;
+ data.other_val = 0;
+ alist_add(&lst, data);
+
+ ptr = lst.data;
+ ut_asserteq_ptr(ptr + 1, alist_end(&lst, struct my_struct));
+
+ data.val = 2;
+ alist_add(&lst, data);
+ ut_asserteq_ptr(ptr + 2, alist_end(&lst, struct my_struct));
+
+ data.val = 3;
+ alist_add(&lst, data);
+ ut_asserteq_ptr(ptr + 3, alist_end(&lst, struct my_struct));
+
+ /* check alist_chk_ptr() */
+ ut_asserteq(true, alist_chk_ptr(&lst, ptr + 2));
+ ut_asserteq(false, alist_chk_ptr(&lst, ptr + 3));
+ ut_asserteq(false, alist_chk_ptr(&lst, ptr + 4));
+ ut_asserteq(true, alist_chk_ptr(&lst, ptr));
+ ut_asserteq(false, alist_chk_ptr(&lst, ptr - 1));
+
+ /* sum all items */
+ sum = 0;
+ alist_for_each(ptr, &lst)
+ sum += ptr->val;
+ ut_asserteq(6, sum);
+
+ /* increment all items */
+ alist_for_each(ptr2, &lst)
+ ptr2->val += 1;
+
+ /* sum all items again */
+ sum = 0;
+ alist_for_each(ptr, &lst)
+ sum += ptr->val;
+ ut_asserteq(9, sum);
+
+ ptr = lst.data;
+ ut_asserteq_ptr(ptr + 3, alist_end(&lst, struct my_struct));
+
+ alist_uninit(&lst);
+
+ /* Check for memory leaks */
+ ut_assertok(ut_check_delta(start));
+
+ return 0;
+}
+LIB_TEST(lib_test_alist_for_each, 0);
--
2.34.1
More information about the U-Boot
mailing list