From 5ebab24637b744f51ff95fbc4c25908d1db00ffd Mon Sep 17 00:00:00 2001 From: Matthias Kruk Date: Tue, 4 May 2021 06:18:24 +0900 Subject: [PATCH] loop: Add cyclic list type Since we will often cycle through monitors, workspaces, and clients, it would be beneficial to have a data structure that assists with that. This commit adds the loop type, which implements a cyclic doubly-linked list. --- loop.c | 150 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ loop.h | 12 +++++ 2 files changed, 162 insertions(+) create mode 100644 loop.c create mode 100644 loop.h diff --git a/loop.c b/loop.c new file mode 100644 index 0000000..19379cd --- /dev/null +++ b/loop.c @@ -0,0 +1,150 @@ +#include +#include +#include +#include "loop.h" + +struct loop { + struct loop *prev; + struct loop *next; + void *data; +}; + +int loop_append(struct loop **loop, void *data) +{ + struct loop *new; + + if(!loop) { + return(-EINVAL); + } + + new = malloc(sizeof(*new)); + + if(!new) { + return(-ENOMEM); + } + + new->data = data; + new->prev = new; + new->next = new; + + if(*loop) { + new->prev = (*loop)->prev; + (*loop)->prev = new; + new->prev->next = new; + new->next = *loop; + } else { + *loop = new; + } + + return(0); +} + +int loop_prepend(struct loop **loop, void *data) +{ + struct loop *new; + + if(!loop) { + return(-EINVAL); + } + + new = malloc(sizeof(*new)); + + if(!new) { + return(-ENOMEM); + } + + new->data = data; + new->prev = new; + new->next = new; + + if(*loop) { + new->prev = (*loop)->prev; + (*loop)->prev = new; + new->prev->next = new; + new->next = *loop; + } + + *loop = new; + + return(0); +} + +int loop_remove(struct loop **loop, void *data) +{ + struct loop *elem; + + if(!loop) { + return(-EINVAL); + } + + if(loop_find(loop, NULL, data, (void**)&elem) < 0) { + return(-ENOENT); + } + + elem->next->prev = elem->prev; + elem->prev->next = elem->next; + + if(*loop == elem) { + if(elem == elem->prev) { + *loop = NULL; + } else { + *loop = elem->prev; + } + } + + free(elem); + + return(0); +} + +int _cmp_ptr(void *left, void *right) +{ + return(left == right); +} + +int loop_find(struct loop **loop, int (*cmp)(void*, void*), void *data, void **dst) +{ + 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) { + *dst = data; + return(0); + } + + cur = cur->next; + } while(cur != *loop); + + return(-ENOENT); +} + +int loop_free(struct loop **loop) +{ + if(!loop) { + return(-EINVAL); + } + + while(*loop) { + struct loop *next; + + next = (*loop)->next; + free(*loop); + + *loop = (*loop == next) ? NULL : next; + } + + return(0); +} diff --git a/loop.h b/loop.h new file mode 100644 index 0000000..fa9de76 --- /dev/null +++ b/loop.h @@ -0,0 +1,12 @@ +#ifndef MWM_LOOP_H +#define MWM_LOOP_H 1 + +struct loop; + +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_free(struct loop **loop); + +#endif /* MWM_LOOP_H */ -- 2.47.3