]> git.corax.cc Git - mwm/commitdiff
loop: Fix several issues in the loop implementation
authorMatthias Kruk <m@m10k.eu>
Sat, 8 May 2021 01:18:33 +0000 (10:18 +0900)
committerMatthias Kruk <m@m10k.eu>
Sat, 8 May 2021 01:18:33 +0000 (10:18 +0900)
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.

loop.c
loop.h

diff --git a/loop.c b/loop.c
index 19379cd9e27cdc310179507425d23bbac37ea680..50370d415c2384a858c1745c36734bc3b854ffe8 100644 (file)
--- 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 fa9de767ab8dbcf3efb9ce5bb6866a75eb327b55..746949b7e4c029efcebc7c3fb2ecc5a3d5277388 100644 (file)
--- 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 */