ptrs_list: add list_foreach_ret 04/273704/6
authorMichal Bloch <m.bloch@samsung.com>
Tue, 12 Apr 2022 17:15:04 +0000 (19:15 +0200)
committerMateusz Majewski <m.majewski2@samsung.com>
Thu, 28 Apr 2022 10:40:00 +0000 (12:40 +0200)
A variant of list_foreach which can return an error code.

Change-Id: Ib3cfcb55114b15674ca342c70b5a8a90d2819633
Signed-off-by: Michal Bloch <m.bloch@samsung.com>
include/ptrs_list.h
src/shared/ptrs_list.c
src/tests/test_ptrs_list_pos.c

index c4a19d9..7fb54bc 100644 (file)
@@ -58,6 +58,14 @@ typedef bool (*cond_cb)(elem_value value, void *user_data);
 typedef void (*apply_cb)(elem_value value, void *user_data);
 
 /**
+ * @brief Apply callback to list element, with return
+ * @param value list element value
+ * @param user_data pointer to user data to be forwarded to callback
+ * @return 0 if everything was ok, nonzero otherwise
+ */
+typedef int (*apply_ret_cb)(elem_value value, void *user_data);
+
+/**
  * @brief Map callback to list element
  * @param value list element value
  * @param user_data pointer to user data to be forwarded to callback
@@ -125,6 +133,15 @@ void list_clear_custom(list_head *head, void *user_data, apply_cb clear);
 void list_foreach(list_head head, void *user_data, apply_cb apply);
 
 /**
+ * @brief Call given callback for all elements in the list
+ * @param[in] head list head
+ * @param[in] user_data pointer to user data to be forwarded to callback
+ * @param[in] apply callback to call for each element in the list
+ * @return The first non-zero return value from the callback, or zero
+ */
+int list_foreach_ret(list_head head, void *user_data, apply_ret_cb apply);
+
+/**
  * @brief Create a new list by looping over a given one
  * @param[in] head list head
  * @param[in] user_data pointer to user data to be forwarded to the callbacks
index 59f84e9..a362b22 100644 (file)
@@ -159,6 +159,20 @@ void list_foreach(list_head head, void *user_data, apply_cb apply)
                apply(elem->value, user_data);
 }
 
+int list_foreach_ret(list_head head, void *user_data, apply_ret_cb apply)
+{
+       assert(apply);
+
+       struct list_elem *elem;
+       for (elem = head; elem; elem = elem->next) {
+               int r = apply(elem->value, user_data);
+               if (r)
+                       return r;
+       }
+
+       return 0;
+}
+
 list_head list_map(list_head head, void *user_data, map_cb map, apply_cb clear)
 {
        assert(map);
index f7c0e5f..b243c42 100644 (file)
 
 #include "test_ptrs_list_wrap.c"
 
+int ret_cb(void *element, void *userdata)
+{
+       if (element == (void *) 0x7AC5A71F)
+               return 789;
+       if (element == (void *) 0xBADF00D)
+               return 321;
+       return 0;
+}
+
+void test_foreach_ret()
+{
+       list_head head = NULL;
+
+       // Some kosher elements, no problems anticipated.
+       list_add(&head, (void *) 0xC0C0A);
+       list_add(&head, (void *) 0xC00CEE);
+       list_add(&head, (void *) 0xC0FFEE);
+       assert(list_foreach_ret(head, NULL, ret_cb) == 0);
+
+       // Add something inedible.
+       list_add(&head, (void *) 0xBADF00D);
+       assert(list_foreach_ret(head, NULL, ret_cb) == 321);
+
+       /* Iteration is in order; insertion happens at the front,
+        * so the newly added element is now returned. */
+       list_add(&head, (void *) 0x7AC5A71F);
+       assert(list_foreach_ret(head, NULL, ret_cb) == 789);
+
+       list_remove(&head, (void *) 0x7AC5A71F);
+       assert(list_foreach_ret(head, NULL, ret_cb) == 321);
+
+       list_remove(&head, (void *) 0xBADF00D);
+       assert(list_foreach_ret(head, NULL, ret_cb) == 0);
+
+       list_clear(&head);
+}
+
 int main(void)
 {
        list_head head = NULL;
@@ -66,5 +103,10 @@ int main(void)
        for (size_t i = 0; i < NELEMS(pointers_to_free); ++i)
                assert(pointers_to_free[i] == NULL);
 
+       // An empty list has no chance to fail.
+       assert(list_foreach_ret(head, NULL, ret_cb) == 0);
+
+       test_foreach_ret();
+
        return 0;
 }