From 9c8a163e1a45c42cd6d2fa62affa66d4c969c541 Mon Sep 17 00:00:00 2001 From: Matthias Kruk Date: Wed, 19 May 2021 08:03:51 +0900 Subject: [PATCH] loop: Add convenience functions and a foreach function without data This commit adds convenience functions to the loop data type that allow the caller to find the elements that come before or after an element in a loop. This further adds functions to shift the position of an element in the loop to the back or the front, and a foreach function that passes only the element pointer to the callback (this is useful for calling things like free() from the foreach function). --- loop.c | 130 +++++++++++++++++++++++++++++++++++++++++++++++++++++---- loop.h | 7 +++- 2 files changed, 129 insertions(+), 8 deletions(-) diff --git a/loop.c b/loop.c index 50370d4..2f74943 100644 --- a/loop.c +++ b/loop.c @@ -154,7 +154,29 @@ int loop_find(struct loop **loop, int (*cmp)(void*, void*), return(err); } -int loop_foreach(struct loop **loop, int(*func)(void*, void*), +int loop_foreach(struct loop **loop, void(*func)(void*)) +{ + struct loop *cur; + + if(!loop) { + return(-EINVAL); + } + + if(!*loop) { + return(0); + } + + cur = *loop; + + do { + func(cur->data); + cur = cur->next; + } while(cur != *loop); + + return(0); +} + +int loop_foreach_with_data(struct loop **loop, int(*func)(void*, void*), void *data) { struct loop *cur; @@ -163,19 +185,19 @@ int loop_foreach(struct loop **loop, int(*func)(void*, void*), return(-EINVAL); } + if(!*loop) { + return(0); + } + cur = *loop; - while(cur) { + do { if(func(cur->data, data) < 0) { break; } cur = cur->next; - - if(cur == *loop) { - break; - } - } + } while(cur != *loop); return(0); } @@ -276,3 +298,97 @@ int loop_get_length(struct loop **loop) return(length); } + +int loop_get_next(struct loop **loop, void *data, void **next) +{ + struct loop *iter; + + if(!loop || !data || !next) { + return(-EINVAL); + } + + if(__loop_find(loop, NULL, data, &iter) < 0) { + return(-ENOENT); + } + + *next = iter->next->data; + return(0); +} + +int loop_get_prev(struct loop **loop, void *data, void **prev) +{ + struct loop *iter; + + if(!loop || !data || !prev) { + return(-EINVAL); + } + + if(__loop_find(loop, NULL, data, &iter) < 0) { + return(-ENOENT); + } + + *prev = iter->prev->data; + return(0); +} + +int loop_shift_forwards(struct loop **loop, void *data) +{ + struct loop *iter; + struct loop *next; + + if(!loop || !data) { + return(-EINVAL); + } + + if(__loop_find(loop, NULL, data, &iter) < 0) { + return(-ENOENT); + } + + next = iter->next; + + iter->prev->next = next; + next->prev = iter->prev; + next->next->prev = iter; + iter->next = next->next; + iter->prev = next; + next->next = iter; + + if(*loop == iter) { + *loop = iter->prev; + } else if(*loop == iter->prev) { + *loop = iter; + } + + return(0); +} + +int loop_shift_backwards(struct loop **loop, void *data) +{ + struct loop *iter; + struct loop *next; + + if(!loop || !data) { + return(-EINVAL); + } + + if(__loop_find(loop, NULL, data, &next) < 0) { + return(-ENOENT); + } + + iter = next->prev; + + iter->prev->next = next; + next->prev = iter->prev; + next->next->prev = iter; + iter->next = next->next; + iter->prev = next; + next->next = iter; + + if(*loop == next) { + *loop = next->next; + } else if(*loop == next->next) { + *loop = next; + } + + return(0); +} diff --git a/loop.h b/loop.h index 746949b..03a5cfc 100644 --- a/loop.h +++ b/loop.h @@ -8,11 +8,16 @@ int loop_append(struct loop **loop, void *data); int loop_prepend(struct loop **loop, void *data); int loop_remove(struct loop **loop, void *data); int loop_find(struct loop **loop, int(*cmp)(void*, void*), void *data, void **dst); -int loop_foreach(struct loop **loop, int(*func)(void*, void*), void*); +int loop_foreach(struct loop **loop, void(*func)(void*)); +int loop_foreach_with_data(struct loop **loop, int(*func)(void*, void*), void*); int loop_free(struct loop **loop); int loop_get_first(struct loop **loop, void**); int loop_get_last(struct loop **loop, void**); int loop_get_length(struct loop **loop); +int loop_get_next(struct loop **loop, void *data, void **next); +int loop_get_prev(struct loop **loop, void *data, void **next); +int loop_shift_backwards(struct loop **loop, void *data); +int loop_shift_forwards(struct loop **loop, void *data); loop_iter_t loop_get_iter(struct loop **loop); loop_iter_t loop_iter_get_next(loop_iter_t iter); -- 2.47.3