mirror of
https://github.com/u-boot/u-boot.git
synced 2025-04-20 20:04:46 +00:00
alist: Add for-loop helpers
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>
This commit is contained in:
parent
1d49f78c36
commit
d785a77d18
3 changed files with 131 additions and 0 deletions
|
@ -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);
|
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
|
* alist_init() - Set up a new object list
|
||||||
*
|
*
|
||||||
|
|
|
@ -118,6 +118,13 @@ int alist_calc_index(const struct alist *lst, const void *ptr)
|
||||||
return index;
|
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)
|
const void *alist_next_ptrd(const struct alist *lst, const void *ptr)
|
||||||
{
|
{
|
||||||
int index = alist_calc_index(lst, ptr);
|
int index = alist_calc_index(lst, ptr);
|
||||||
|
|
|
@ -292,3 +292,77 @@ static int lib_test_alist_next(struct unit_test_state *uts)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
LIB_TEST(lib_test_alist_next, 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);
|
||||||
|
|
Loading…
Add table
Reference in a new issue