From d278dd013dcdc280d74257c7d8554d92c1298a71 Mon Sep 17 00:00:00 2001 From: Elias Fleckenstein Date: Sun, 3 Apr 2022 21:45:39 +0200 Subject: [PATCH] Add transformers to iterator functions --- bits/wrappers.h | 12 ++++++------ list.c | 10 +++++----- list.h | 14 +++++++------- map.c | 16 ++++++++++++---- map.h | 16 ++++++++++++---- queue.c | 10 +++++----- queue.h | 4 ++-- test/test_list.c | 2 +- test/test_refcount_map.c | 2 +- test/test_tree.c | 9 +++++---- tree.c | 20 ++++++++++---------- tree.h | 14 +++++++------- 12 files changed, 73 insertions(+), 56 deletions(-) diff --git a/bits/wrappers.h b/bits/wrappers.h index 60d8784..66093a2 100644 --- a/bits/wrappers.h +++ b/bits/wrappers.h @@ -1,32 +1,32 @@ #define WRAP_NODE_FUNCTIONS(Type, prefix) \ - void *prefix ## add(Type *self, void *dat, Comparator cmp, Transformer func) \ + void *prefix ## add(Type *self, void *dat, Comparator cmp, Transformer trans) \ { \ Type ## Node **node = prefix ## nfd(self, dat, cmp); \ \ if (! *node) \ - prefix ## nmk(self, node, func ? func(dat) : dat); \ + prefix ## nmk(self, node, trans ? trans(dat) : dat); \ \ return (*node)->dat; \ } \ \ - void *prefix ## get(Type *self, void *key, Comparator cmp, Transformer func) \ + void *prefix ## get(Type *self, void *key, Comparator cmp, Transformer trans) \ { \ Type ## Node **node = prefix ## nfd(self, key, cmp); \ \ if (! *node) \ return NULL; \ \ - return func ? func((*node)->dat) : (*node)->dat; \ + return trans ? trans((*node)->dat) : (*node)->dat; \ } \ \ - void *prefix ## del(Type *self, void *key, Comparator cmp, Transformer func) \ + void *prefix ## del(Type *self, void *key, Comparator cmp, Transformer trans) \ { \ Type ## Node **node = prefix ## nfd(self, key, cmp); \ \ if (! *node) \ return NULL; \ \ - void *dat = func ? func((*node)->dat) : (*node)->dat; \ + void *dat = trans ? trans((*node)->dat) : (*node)->dat; \ prefix ## nrm(self, node); \ return dat; \ } diff --git a/list.c b/list.c index f136706..d8416d9 100644 --- a/list.c +++ b/list.c @@ -50,19 +50,19 @@ void list_nrm(List *list, ListNode **node) free(old); } -void list_itr(List *list, Iterator func, void *arg) +void list_itr(List *list, Iterator iter, void *arg, Transformer trans) { LIST_ITERATE(list, node) - func(node->dat, arg); + iter(trans ? trans(node->dat) : node->dat, arg); } -void list_clr(List *list, Iterator func, void *arg) +void list_clr(List *list, Iterator iter, void *arg, Transformer trans) { for (ListNode *node = list->fst; node != NULL;) { ListNode *next = node->nxt; - if (func) - func(node->dat, arg); + if (iter) + iter(trans ? trans(node->dat) : node->dat, arg); free(node); node = next; diff --git a/list.h b/list.h index 5adb33e..eb8f97b 100644 --- a/list.h +++ b/list.h @@ -33,7 +33,7 @@ void list_ini(List *list); This function should be called before any other function is called on the list. */ -void *list_add(List *list, void *dat, Comparator cmp, Transformer func); +void *list_add(List *list, void *dat, Comparator cmp, Transformer trans); /* Add an element to the list. @@ -41,14 +41,14 @@ void *list_add(List *list, void *dat, Comparator cmp, Transformer func); Otherwise, return added element. */ -void *list_get(List *list, void *key, Comparator cmp, Transformer func); +void *list_get(List *list, void *key, Comparator cmp, Transformer trans); /* Get an element from the list. The first matching element is returned, or NULL if none found. */ -void *list_del(List *list, void *key, Comparator cmp, Transformer func); +void *list_del(List *list, void *key, Comparator cmp, Transformer trans); /* Delete an element from the list. @@ -79,18 +79,18 @@ void list_nrm(List *list, ListNode **node); Remove the node at the given location. */ -void list_itr(List *list, Iterator func, void *arg); +void list_itr(List *list, Iterator iter, void *arg, Transformer trans); /* Iterate over the list. - Calls func on every element, with the extra argument arg. + Calls iter on every element, with the extra argument arg. Note: the LIST_ITERATE macro can be used to do this without function calls. */ -void list_clr(List *list, Iterator func, void *arg); +void list_clr(List *list, Iterator iter, void *arg, Transformer trans); /* Iterates over the list and deletes all elements. - Calls func on every element, with the extra argument arg. + Calls iter on every element, with the extra argument arg. The list is empty afterwards. */ diff --git a/map.c b/map.c index f2593ec..20bccb6 100644 --- a/map.c +++ b/map.c @@ -32,7 +32,7 @@ void map_dst(Map *map) pthread_rwlock_destroy(&map->clk); } -void map_cnl(Map *map, Iterator func, void *arg, TreeTraversionOrder order) +void map_cnl(Map *map, Iterator iter, void *arg, Transformer trans, TreeTraversionOrder order) { pthread_rwlock_wrlock(&map->clk); map->cnl = true; @@ -40,18 +40,18 @@ void map_cnl(Map *map, Iterator func, void *arg, TreeTraversionOrder order) pthread_rwlock_wrlock(&map->tlk); pthread_rwlock_unlock(&map->clk); - tree_clr(&map->tre, func, arg, order); + tree_clr(&map->tre, iter, arg, trans, order); pthread_rwlock_unlock(&map->tlk); } #define WRAP_TREE_FUNC(name, write) \ - void *map_ ## name(Map *map, void *dat, Comparator cmp, Transformer func) \ + void *map_ ## name(Map *map, void *dat, Comparator cmp, Transformer trans) \ { \ if (! get_lock(map, write)) \ return NULL; \ \ - dat = tree_ ## name(&map->tre, dat, cmp, func); \ + dat = tree_ ## name(&map->tre, dat, cmp, trans); \ pthread_rwlock_unlock(&map->tlk); \ return dat; \ } @@ -59,3 +59,11 @@ void map_cnl(Map *map, Iterator func, void *arg, TreeTraversionOrder order) WRAP_TREE_FUNC(add, true) WRAP_TREE_FUNC(get, false) WRAP_TREE_FUNC(del, true) + +void map_trv(Map *map, Iterator iter, void *arg, Transformer trans, TreeTraversionOrder order) +{ + if (! get_lock(map, false)) + return; + + tree_trv(&map->tre, iter, arg, trans, order); +} diff --git a/map.h b/map.h index 1a10606..08d3fd0 100644 --- a/map.h +++ b/map.h @@ -38,7 +38,7 @@ void map_dst(Map *map); Make sure to cancel the map before destroying it, to avoid memory leaks. */ -void map_cnl(Map *map, Iterator func, void *arg, TreeTraversionOrder order); +void map_cnl(Map *map, Iterator iter, void *arg, Transformer trans, TreeTraversionOrder order); /* [Thread Safe] Cancels and clears the map. @@ -52,7 +52,7 @@ void map_cnl(Map *map, Iterator func, void *arg, TreeTraversionOrder order); If no callback is given, the traversion order is irrelevant. */ -void *map_add(Map *map, void *dat, Comparator cmp, Transformer func); +void *map_add(Map *map, void *dat, Comparator cmp, Transformer trans); /* [Thread Safe] Add an element to the map. @@ -61,16 +61,24 @@ void *map_add(Map *map, void *dat, Comparator cmp, Transformer func); Otherwise, return added element. */ -void *map_get(Map *map, void *key, Comparator cmp, Transformer func); +void *map_get(Map *map, void *key, Comparator cmp, Transformer trans); /* [Thread Safe] Get an element from the map, or return NULL if none found. */ -void *map_del(Map *map, void *key, Comparator cmp, Transformer func); +void *map_del(Map *map, void *key, Comparator cmp, Transformer trans); /* [Thread Safe] Delete an element from the map and return it, or NULL if none found. */ +void map_trv(Map *map, Iterator iter, void *arg, Transformer trans, TreeTraversionOrder order); +/* + [Thread Safe] + Traverse the map. + Calls iter on every element, with the extra argument arg. +*/ + + #endif diff --git a/queue.c b/queue.c index eeba91c..ccef905 100644 --- a/queue.c +++ b/queue.c @@ -15,9 +15,9 @@ void queue_del(Queue *queue) pthread_mutex_destroy(&queue->mtx); } -void queue_clr(Queue *queue, Iterator func, void *arg) +void queue_clr(Queue *queue, Iterator iter, void *arg, Transformer trans) { - list_clr(&queue->lst, func, arg); + list_clr(&queue->lst, iter, arg, trans); } bool queue_enq(Queue *queue, void *dat) @@ -35,7 +35,7 @@ bool queue_enq(Queue *queue, void *dat) return success; } -void *queue_deq(Queue *queue, Transformer func) +void *queue_deq(Queue *queue, Transformer trans) { void *dat = NULL; @@ -46,8 +46,8 @@ void *queue_deq(Queue *queue, Transformer func) dat = (*node)->dat; list_nrm(&queue->lst, node); - if (func) - dat = func(dat); + if (trans) + dat = trans(dat); } else { pthread_cond_wait(&queue->cnd, &queue->mtx); } diff --git a/queue.h b/queue.h index 2a71930..8c758e2 100644 --- a/queue.h +++ b/queue.h @@ -40,7 +40,7 @@ void queue_del(Queue *queue); list is cleared before calling this function. */ -void queue_clr(Queue *queue, Iterator func, void *arg); +void queue_clr(Queue *queue, Iterator iter, void *arg, Transformer trans); /* Clears the queue. @@ -58,7 +58,7 @@ bool queue_enq(Queue *queue, void *dat); Notifies waiting consumer threads. */ -void *queue_deq(Queue *queue, Transformer func); +void *queue_deq(Queue *queue, Transformer trans); /* [Thread Safe] Dequeue an element. diff --git a/test/test_list.c b/test/test_list.c index b261dbd..7ba8992 100644 --- a/test/test_list.c +++ b/test/test_list.c @@ -42,6 +42,6 @@ int main() assert(list_get(&list, &a, &cmp_int, NULL) == NULL); printf("testing clr\n"); - list_clr(&list, NULL, NULL); + list_clr(&list, NULL, NULL, NULL); assert(list_get(&list, &b, &cmp_int, NULL) == NULL); } diff --git a/test/test_refcount_map.c b/test/test_refcount_map.c index 75291bf..9333c00 100644 --- a/test/test_refcount_map.c +++ b/test/test_refcount_map.c @@ -137,7 +137,7 @@ int main() results[i][0] += results[i][j]; } - map_cnl(&map, (void *) &refcount_drp, NULL, 0); + map_cnl(&map, (void *) &refcount_drp, NULL, NULL, 0); map_dst(&map); printf("Time: 10 seconds\n"); diff --git a/test/test_tree.c b/test/test_tree.c index 6166cf0..ae5ec5b 100644 --- a/test/test_tree.c +++ b/test/test_tree.c @@ -11,9 +11,10 @@ int cmp_int(const void *ia, const void *ib) return *(const int *) ia - *(const int *) ib; } -void clear_callback(void *ia, void *ib) +void clear_callback(int *ia, int *ib) { - assert(*(int *) ia > *(int *) ib); + assert(*ia >= *ib); + *ib = *ia; free(ia); } @@ -54,7 +55,7 @@ int main() assert(tree_get(&tree, &a, &cmp_int, NULL) == NULL); printf("testing clr\n"); - tree_clr(&tree, NULL, NULL, 0); + tree_clr(&tree, NULL, NULL, NULL, 0); assert(tree_get(&tree, &b, &cmp_int, NULL) == NULL); printf("testing order and speed with %d elements\n", (int) NUM_ELEMENTS); @@ -67,5 +68,5 @@ int main() } int last = -1; - tree_clr(&tree, &clear_callback, &last, TRAVERSION_INORDER); + tree_clr(&tree, (void *) &clear_callback, &last, NULL, TRAVERSION_INORDER); } diff --git a/tree.c b/tree.c index aa55a12..e4206b2 100644 --- a/tree.c +++ b/tree.c @@ -17,16 +17,16 @@ static inline TreeNode **search(TreeNode **node, void *key, Comparator cmp) return search(&(*node)->rgt, key, cmp); } -static inline void traverse(TreeNode *node, Iterator func, void *arg, TreeTraversionOrder order, int delete) +static inline void traverse(TreeNode *node, Iterator iter, void *arg, Transformer trans, TreeTraversionOrder order, int delete) { if (! node) return; - if (func && order == TRAVERSION_PREORDER ) func(node->dat, arg); - traverse(node->lft, func, arg, order, delete); - if (func && order == TRAVERSION_INORDER ) func(node->dat, arg); - traverse(node->rgt, func, arg, order, delete); - if (func && order == TRAVERSION_POSTORDER) func(node->dat, arg); + if (iter && order == TRAVERSION_PREORDER ) iter(trans ? trans(node->dat) : node->dat, arg); + traverse(node->lft, iter, arg, trans, order, delete); + if (iter && order == TRAVERSION_INORDER ) iter(trans ? trans(node->dat) : node->dat, arg); + traverse(node->rgt, iter, arg, trans, order, delete); + if (iter && order == TRAVERSION_POSTORDER) iter(trans ? trans(node->dat) : node->dat, arg); if (delete) free(node); @@ -68,13 +68,13 @@ void tree_nrm(__attribute__((unused)) Tree *tree, TreeNode **node) free(old); } -void tree_trv(Tree *tree, Iterator func, void *arg, TreeTraversionOrder order) +void tree_trv(Tree *tree, Iterator iter, void *arg, Transformer trans, TreeTraversionOrder order) { - traverse(tree->rot, func, arg, order, 0); + traverse(tree->rot, iter, arg, trans, order, 0); } -void tree_clr(Tree *tree, Iterator func, void *arg, TreeTraversionOrder order) +void tree_clr(Tree *tree, Iterator iter, void *arg, Transformer trans, TreeTraversionOrder order) { - traverse(tree->rot, func, arg, order, 1); + traverse(tree->rot, iter, arg, trans, order, 1); tree_ini(tree); } diff --git a/tree.h b/tree.h index 5c90e10..d253321 100644 --- a/tree.h +++ b/tree.h @@ -43,7 +43,7 @@ void tree_ini(Tree *tree); This function should be called before any other function is called on the tree. */ -void *tree_add(Tree *tree, void *dat, Comparator cmp, Transformer func); +void *tree_add(Tree *tree, void *dat, Comparator cmp, Transformer trans); /* Add an element to the tree. @@ -51,12 +51,12 @@ void *tree_add(Tree *tree, void *dat, Comparator cmp, Transformer func); Otherwise, return added element. */ -void *tree_get(Tree *tree, void *key, Comparator cmp, Transformer func); +void *tree_get(Tree *tree, void *key, Comparator cmp, Transformer trans); /* Get an element from the tree, or return NULL if none found. */ -void *tree_del(Tree *tree, void *key, Comparator cmp, Transformer func); +void *tree_del(Tree *tree, void *key, Comparator cmp, Transformer trans); /* Delete an element from the tree and return it, or NULL if none found. */ @@ -79,16 +79,16 @@ void tree_nrm(Tree *tree, TreeNode **node); Remove the node at the given location. */ -void tree_trv(Tree *tree, Iterator func, void *arg, TreeTraversionOrder order); +void tree_trv(Tree *tree, Iterator iter, void *arg, Transformer trans, TreeTraversionOrder order); /* Traverse the tree. - Calls func on every element, with the extra argument arg. + Calls iter on every element, with the extra argument arg. */ -void tree_clr(Tree *tree, Iterator func, void *arg, TreeTraversionOrder order); +void tree_clr(Tree *tree, Iterator iter, void *arg, Transformer trans, TreeTraversionOrder order); /* Traverses the tree and deletes all elements. - Calls func on every element, with the extra argument arg. + Calls iter on every element, with the extra argument arg. The tree is empty afterwards. If no callback is given, the traversion order is irrelevant. -- 2.44.0