From: Matthias Kruk Date: Sat, 8 May 2021 01:18:33 +0000 (+0900) Subject: loop: Fix several issues in the loop implementation X-Git-Url: https://git.corax.cc/?a=commitdiff_plain;h=bbd4472b4dcba613711460044e678847d6aaa99a;p=mwm loop: Fix several issues in the loop implementation There were several bugs in the loop implementation, most notably in the search and remove methods. This commit fixes the bugs so that it is possible to retrieve elements and remove elements from loop structures. --- diff --git a/loop.c b/loop.c index 19379cd..50370d4 100644 --- a/loop.c +++ b/loop.c @@ -9,6 +9,11 @@ struct loop { void *data; }; +static int _cmp_ptr(void *left, void *right) +{ + return(left == right ? 0 : 1); +} + int loop_append(struct loop **loop, void *data) { struct loop *new; @@ -69,6 +74,41 @@ int loop_prepend(struct loop **loop, void *data) return(0); } +int __loop_find(struct loop **loop, + int (*cmp)(void*, void*), + void *data, + struct loop **iter) +{ + struct loop *cur; + + if(!loop) { + return(-EINVAL); + } + + if(!*loop) { + return(-ENOENT); + } + + if(!cmp) { + cmp = _cmp_ptr; + } + + cur = *loop; + + do { + if(cmp(cur->data, data) == 0) { + if(iter) { + *iter = cur; + } + return(0); + } + + cur = cur->next; + } while(cur != *loop); + + return(-ENOENT); +} + int loop_remove(struct loop **loop, void *data) { struct loop *elem; @@ -77,7 +117,7 @@ int loop_remove(struct loop **loop, void *data) return(-EINVAL); } - if(loop_find(loop, NULL, data, (void**)&elem) < 0) { + if(__loop_find(loop, NULL, data, &elem) < 0) { return(-ENOENT); } @@ -85,10 +125,10 @@ int loop_remove(struct loop **loop, void *data) elem->prev->next = elem->next; if(*loop == elem) { - if(elem == elem->prev) { + if(elem == elem->next) { *loop = NULL; } else { - *loop = elem->prev; + *loop = elem->next; } } @@ -97,12 +137,25 @@ int loop_remove(struct loop **loop, void *data) return(0); } -int _cmp_ptr(void *left, void *right) +int loop_find(struct loop **loop, int (*cmp)(void*, void*), + void *data, void **dst) { - return(left == right); + struct loop *elem; + int err; + + err = __loop_find(loop, cmp, data, &elem); + + if(!err) { + if(dst) { + *dst = elem->data; + } + } + + return(err); } -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 *data) { struct loop *cur; @@ -110,25 +163,21 @@ int loop_find(struct loop **loop, int (*cmp)(void*, void*), void *data, void **d return(-EINVAL); } - if(!*loop) { - return(-ENOENT); - } - - if(!cmp) { - cmp = _cmp_ptr; - } cur = *loop; - do { - if(cmp(cur->data, data) == 0) { - *dst = data; - return(0); - } + while(cur) { + if(func(cur->data, data) < 0) { + break; + } - cur = cur->next; - } while(cur != *loop); + cur = cur->next; - return(-ENOENT); + if(cur == *loop) { + break; + } + } + + return(0); } int loop_free(struct loop **loop) @@ -140,11 +189,90 @@ int loop_free(struct loop **loop) while(*loop) { struct loop *next; + (*loop)->prev->next = NULL; next = (*loop)->next; + free(*loop); - *loop = (*loop == next) ? NULL : next; + *loop = next; } return(0); } + +int loop_get_first(struct loop **loop, void **data) +{ + if(!loop || !data) { + return(-EINVAL); + } + + if(!*loop) { + return(-ENOENT); + } + + *data = (*loop)->data; + return(0); +} + +int loop_get_last(struct loop **loop, void **data) +{ + if(!loop || !data) { + return(-EINVAL); + } + + if(!*loop) { + return(-ENOENT); + } + + *data = (*loop)->prev->data; + return(0); +} + +loop_iter_t loop_get_iter(struct loop **loop) +{ + if(!loop) { + return(NULL); + } + + return(*loop); +} + +loop_iter_t loop_iter_get_next(loop_iter_t iter) +{ + return(iter->next); +} + +loop_iter_t loop_iter_get_prev(loop_iter_t iter) +{ + return(iter->prev); +} + +void* loop_iter_get_data(loop_iter_t iter) +{ + return(iter->data); +} + +int loop_get_length(struct loop **loop) +{ + struct loop *cur; + + int length; + + if(!loop) { + return(-EINVAL); + } + + if(!*loop) { + return(0); + } + + length = 0; + cur = *loop; + + do { + length++; + cur = cur->next; + } while(cur != *loop); + + return(length); +} diff --git a/loop.h b/loop.h index fa9de76..746949b 100644 --- a/loop.h +++ b/loop.h @@ -2,11 +2,24 @@ #define MWM_LOOP_H 1 struct loop; +typedef struct loop* loop_iter_t; 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_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); + +loop_iter_t loop_get_iter(struct loop **loop); +loop_iter_t loop_iter_get_next(loop_iter_t iter); +loop_iter_t loop_iter_get_prev(loop_iter_t iter); +void* loop_iter_get_data(loop_iter_t iter); + +#define loop_iter_inc(iter) ((iter) = loop_iter_get_next((iter))) +#define loop_iter_dec(iter) ((iter) = loop_iter_get_prev((iter))) #endif /* MWM_LOOP_H */