summaryrefslogtreecommitdiff
path: root/osi
diff options
context:
space:
mode:
authorAndre Eisenbach <eisenbach@google.com>2016-01-13 21:20:59 -0800
committerAndre Eisenbach <eisenbach@google.com>2016-01-15 17:02:54 +0000
commit760fb7083b1781c9519fb6a36e46d7ab5d5efb30 (patch)
treea236ecf596d7c66c2285c439a57fb4cc8572c90d /osi
parent15df6d411e871e2e1366a3599bb990ce0cb9aae1 (diff)
downloadandroid-system-bt-760fb7083b1781c9519fb6a36e46d7ab5d5efb30.tar.gz
android-system-bt-760fb7083b1781c9519fb6a36e46d7ab5d5efb30.tar.xz
Make list_foreach() more useful
- Changed |callback| return type to bool to be able to interrupt iteration (to find specific elements for example). - Added new |extra| parameter for |callback| so a pointer can be passed in to receive output values or to pass in criteria etc. - Also added unit tests. Change-Id: Id1ddcbabf55292f701d0277f2a1e9ec261b9fbde
Diffstat (limited to 'osi')
-rw-r--r--osi/include/list.h14
-rw-r--r--osi/src/list.c6
-rw-r--r--osi/test/list_test.cpp62
3 files changed, 77 insertions, 5 deletions
diff --git a/osi/include/list.h b/osi/include/list.h
index da38c2f..b1513c0 100644
--- a/osi/include/list.h
+++ b/osi/include/list.h
@@ -10,7 +10,12 @@ struct list_t;
typedef struct list_t list_t;
typedef void (*list_free_cb)(void *data);
-typedef bool (*list_iter_cb)(void *data);
+
+// Iterator callback prototype used for |list_foreach|.
+// |data| represents the list item currently being iterated, |context| is a
+// user defined value passed into |list_foreach|.
+// Callback must return true to continue iterating or false to stop iterating.
+typedef bool (*list_iter_cb)(void *data, void *context);
// Returns a new, empty list. Returns NULL if not enough memory could be allocated
// for the list structure. The returned list must be freed with |list_free|. The
@@ -73,12 +78,15 @@ bool list_remove(list_t *list, void *data);
// same state it was in after |list_new|. |list| may not be NULL.
void list_clear(list_t *list);
-// Iterates through the entire |list| and calls |callback| for each data element.
+// Iterates through the |list| and calls |callback| for each data element. Iteration
+// continues until |callback| returns false. The function returns the result of the
+// last executed |callback| or true if the list is empty. |context| is passed to
+// |callback| on each iteration.
// If the list is empty, |callback| will never be called. It is safe to mutate the
// list inside the callback. If an element is added before the node being visited,
// there will be no callback for the newly-inserted node. Neither |list| nor
// |callback| may be NULL.
-void list_foreach(const list_t *list, list_iter_cb callback);
+bool list_foreach(const list_t *list, list_iter_cb callback, void *context);
// Returns an iterator to the first element in |list|. |list| may not be NULL.
// The returned iterator is valid as long as it does not equal the value returned
diff --git a/osi/src/list.c b/osi/src/list.c
index f5f5889..61d19f0 100644
--- a/osi/src/list.c
+++ b/osi/src/list.c
@@ -168,15 +168,17 @@ void list_clear(list_t *list) {
list->length = 0;
}
-void list_foreach(const list_t *list, list_iter_cb callback) {
+bool list_foreach(const list_t *list, list_iter_cb callback, void *context) {
assert(list != NULL);
assert(callback != NULL);
for (list_node_t *node = list->head; node; ) {
list_node_t *next = node->next;
- callback(node->data);
+ if (!callback(node->data, context))
+ return false;
node = next;
}
+ return true;
}
list_node_t *list_begin(const list_t *list) {
diff --git a/osi/test/list_test.cpp b/osi/test/list_test.cpp
index ce5a158..de01b19 100644
--- a/osi/test/list_test.cpp
+++ b/osi/test/list_test.cpp
@@ -146,3 +146,65 @@ TEST_F(ListTest, test_list_next) {
EXPECT_EQ(list_next(list_begin(list)), list_end(list));
list_free(list);
}
+
+static bool list_callback_sum(void *data, void *context) {
+ assert(data);
+ assert(context);
+ int *sum = (int *)context;
+ int *value = (int *)data;
+ *sum += *value;
+ return true;
+}
+
+static bool list_callback_find_int(void *data, void *context) {
+ assert(data);
+ assert(context);
+ return (*(int *)data != *(int *)context);
+}
+
+TEST_F(ListTest, test_list_foreach_full) {
+ list_t *list = list_new(NULL);
+
+ // Fill in test data
+ int x[] = { 1, 2, 3, 4, 5 };
+ for (size_t i = 0; i < ARRAY_SIZE(x); ++i)
+ list_append(list, &x[i]);
+ EXPECT_EQ(list_length(list), 5);
+
+ // Test complete iteration
+ int sum = 0;
+ bool rc = list_foreach(list, list_callback_sum, &sum);
+ EXPECT_EQ(sum, 15);
+ EXPECT_TRUE(rc);
+
+ list_free(list);
+}
+
+TEST_F(ListTest, test_list_foreach_partial) {
+ list_t *list = list_new(NULL);
+
+ // Fill in test data
+ int x[] = { 1, 2, 3, 4, 5 };
+ for (size_t i = 0; i < ARRAY_SIZE(x); ++i)
+ list_append(list, &x[i]);
+ EXPECT_EQ(list_length(list), 5);
+
+ // Test partial iteration
+ int find = 4;
+ bool rc = list_foreach(list, list_callback_find_int, &find);
+ EXPECT_FALSE(rc);
+
+ find = 1;
+ rc = list_foreach(list, list_callback_find_int, &find);
+ EXPECT_FALSE(rc);
+
+ find = 5;
+ rc = list_foreach(list, list_callback_find_int, &find);
+ EXPECT_FALSE(rc);
+
+ find = 0;
+ rc = list_foreach(list, list_callback_find_int, &find);
+ EXPECT_TRUE(rc);
+
+ list_free(list);
+}