]> git.dujemihanovic.xyz Git - u-boot.git/commitdiff
alist: Add for-loop helpers
authorSimon Glass <sjg@chromium.org>
Sat, 19 Oct 2024 15:21:45 +0000 (09:21 -0600)
committerTom Rini <trini@konsulko.com>
Mon, 4 Nov 2024 03:27:12 +0000 (21:27 -0600)
Add some macros which permit easy iteration through an alist, similar to
those provided by the 'list' implementation.

Signed-off-by: Simon Glass <sjg@chromium.org>
include/alist.h
lib/alist.c
test/lib/alist.c

index 97523af37a6536c71581dcdaa989f5413ac00904..0090b9c0eb1cae92c8ddf1a3a9ff4ad748363828 100644 (file)
@@ -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
  *
index 7730fe0d473f04a5ceab9c46786c6ceb0bf4a871..1a4b4fb9c40c263ec75f77611e74c7fe900aa856 100644 (file)
@@ -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);
index 96092affec93462651f6e64bfcd3d012a1bf62fd..1715a22584c280b79d99f10be533a11442dad206 100644 (file)
@@ -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);