diff --git a/configure.ac b/configure.ac index e655205..45dac5a 100644 --- a/configure.ac +++ b/configure.ac @@ -53,6 +53,9 @@ AM_CFLAGS="${AM_CFLAGS} ${MEM_OPT_FLAGS}" AM_CFLAGS="${AM_CFLAGS} ${CFLAGS}" AC_SUBST(AM_CFLAGS) +AM_LDFLAGS="" +AC_SUBST(AM_LDFLAGS) + AC_CONFIG_FILES([Makefile docs/Makefile tests/Makefile diff --git a/include/tr/hash.h b/include/tr/hash.h index 793894f..9792d3d 100644 --- a/include/tr/hash.h +++ b/include/tr/hash.h @@ -28,25 +28,25 @@ #include "trbase.h" #include "tr/tree.h" -#define TR_HASH_IS_EMPTY(h) ((h)->root) +#define TR_HASH_IS_EMPTY(h) ((h)->tree->root) TR_CLASS(TR_Hash) { - TR_Tree root; + TR_Tree tree; int cleanup_no_free; }; TR_INSTANCE_INIT(TR_Hash); TR_CLASSVARS_DECL(TR_Hash) {}; -#define TR_hashEmpty(hash) (NULL == (hash)->root) +//#define TR_hashEmpty(hash) (NULL == (hash)->tree->root) -void * TR_hashAdd(TR_Hash, void *); -void * TR_hashDelete(TR_Hash, const char *, size_t); -void * TR_hashGet(TR_Hash, const char *, size_t); -void * TR_hashGetFirst(TR_Hash); -void * TR_hashDeleteByVal(TR_Hash, unsigned long); -void * TR_hashGetByVal(TR_Hash, unsigned long); -void TR_hashEach(TR_Hash, const void *, void (*)(const void *, const void *)); -void TR_hashCleanup(TR_Hash); +void * TR_hashAdd(TR_Hash, void *); +void * TR_hashDelete(TR_Hash, const char *, size_t); +void * TR_hashGet(TR_Hash, const char *, size_t); +void * TR_hashGetFirst(TR_Hash); +void * TR_hashDeleteByVal(TR_Hash, unsigned long); +void * TR_hashGetByVal(TR_Hash, unsigned long); +unsigned long TR_hashEach(TR_Hash, const void *, void (*)(const void *, const void *)); +void TR_hashCleanup(TR_Hash); #endif // __TR_HASH_H__ diff --git a/include/tr/tree.h b/include/tr/tree.h index 6ff6040..353fc08 100644 --- a/include/tr/tree.h +++ b/include/tr/tree.h @@ -26,14 +26,20 @@ #include "tr/tree_macros.h" #include "trbase.h" -TR_CLASS(TR_Tree) { +TR_CLASS(TR_TreeNode) { void * data; TR_rbColor color; - TR_Tree parent; - TR_Tree left; - TR_Tree right; + TR_TreeNode parent; + TR_TreeNode left; + TR_TreeNode right; +}; +TR_INSTANCE_INIT(TR_TreeNode); +TR_CLASSVARS_DECL(TR_TreeNode) {}; + +TR_CLASS(TR_Tree) { + TR_TreeNode root; }; TR_INSTANCE_INIT(TR_Tree); TR_CLASSVARS_DECL(TR_Tree) {}; @@ -41,11 +47,11 @@ TR_CLASSVARS_DECL(TR_Tree) {}; typedef int (*TR_TreeComp)(const void *, const void *); typedef void (*TR_TreeAction)(const void *, const void *, const int); -void * TR_treeFind(TR_Tree, const void *, TR_TreeComp); -void * TR_treeInsert(TR_Tree *, const void *, TR_TreeComp); -void * TR_treeDelete(TR_Tree *, const void *, TR_TreeComp); -void TR_treeWalk(TR_Tree, const void *, TR_TreeAction); -void TR_treeDestroy(TR_Tree *, TR_TreeAction); +void * TR_treeFind(TR_Tree, const void *, TR_TreeComp); +void * TR_treeInsert(TR_Tree, const void *, TR_TreeComp); +void * TR_treeDelete(TR_Tree, const void *, TR_TreeComp); +unsigned long TR_treeWalk(TR_Tree, const void *, TR_TreeAction); +void TR_treeDestroy(TR_Tree, TR_TreeAction); #endif // __TR_TREE_H__ diff --git a/src/Makefile.am b/src/Makefile.am index 690c7c3..bee8a22 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,7 +1,8 @@ ACLOCAL_AMFLAGS = -I m4 AUTOMAKE_OPTIONS = subdir-objects -AM_CFLAGS += -I../include/ +AM_CFLAGS += -I../include/ -std=c99 -DREENTRANT -lpthread +AM_LDFLAGS += -lpthread TRDATALIBS = cbuf/libcbuf.la \ hash/libhash.la \ @@ -13,5 +14,6 @@ lib_LTLIBRARIES = libtrdata.la libtrdata_la_SOURCES = libtrdata_la_CFLAGS = $(AM_CFLAGS) libtrdata_la_LIBADD = $(TRDATALIBS) +libtrdata_la_LDFLAGS = -version-info 0:0:0 $(AM_LDFLAGS) SUBDIRS = cbuf hash queue tree diff --git a/src/cbuf/Makefile.am b/src/cbuf/Makefile.am index 834d30c..6249a4b 100644 --- a/src/cbuf/Makefile.am +++ b/src/cbuf/Makefile.am @@ -1,7 +1,8 @@ ACLOCAL_AMFLAGS = -I m4 AUTOMAKE_OPTIONS = subdir-objects -AM_CFLAGS += -I../../include/ +AM_CFLAGS += -I../../include/ -std=c99 -DREENTRANT -lpthread +AM_LDFLAGS += -lpthread CB = cbuf.c read.c \ get_line.c set_data.c get_data.c \ @@ -14,3 +15,4 @@ noinst_LTLIBRARIES = libcbuf.la libcbuf_la_SOURCES = $(CB) libcbuf_la_CFLAGS = $(AM_CFLAGS) +libcbuf_la_LIBADD = $(AM_LDFLAGS) diff --git a/src/hash/Makefile.am b/src/hash/Makefile.am index 615fba0..6bbc9c5 100644 --- a/src/hash/Makefile.am +++ b/src/hash/Makefile.am @@ -1,7 +1,8 @@ ACLOCAL_AMFLAGS = -I m4 AUTOMAKE_OPTIONS = subdir-objects -AM_CFLAGS += -I../../include/ +AM_CFLAGS += -I../../include/ -std=c99 -DREENTRANT -lpthread +AM_LDFLAGS += -lpthread HASH = hash.c add.c get.c get_first.c delete.c each.c value.c \ cleanup.c interface/hashable.c @@ -10,3 +11,4 @@ noinst_LTLIBRARIES = libhash.la libhash_la_SOURCES = $(HASH) libhash_la_CFLAGS = $(AM_CFLAGS) +libhash_la_LIBADD = $(AM_LDFLAGS) diff --git a/src/hash/add.c b/src/hash/add.c index 6ea8692..83d185c 100644 --- a/src/hash/add.c +++ b/src/hash/add.c @@ -48,7 +48,7 @@ hashAddComp(const void * a, const void * b) void * TR_hashAdd(TR_Hash this, void * operand) { - void * found = TR_treeInsert(&this->root, operand, hashAddComp); + void * found = TR_treeInsert(this->tree, operand, hashAddComp); if (NULL == found) { return NULL; diff --git a/src/hash/cleanup.c b/src/hash/cleanup.c index 5245ea3..a0c6290 100644 --- a/src/hash/cleanup.c +++ b/src/hash/cleanup.c @@ -36,10 +36,12 @@ void TR_hashCleanup(TR_Hash this) { if (this->cleanup_no_free) { - TR_treeDestroy(&(this->root), NULL); + TR_treeDestroy(this->tree, NULL); } else { - TR_treeDestroy(&(this->root), tDelete); + TR_treeDestroy(this->tree, tDelete); } + + TR_delete(this->tree); } // vim: set ts=4 sw=4: diff --git a/src/hash/delete.c b/src/hash/delete.c index 2013853..e0887d4 100644 --- a/src/hash/delete.c +++ b/src/hash/delete.c @@ -51,7 +51,7 @@ TR_hashDelete(TR_Hash this, const char * search, size_t nsearch) unsigned long hash = TR_sdbm((const unsigned char *)search, nsearch); void * found = NULL; - found = TR_treeDelete(&(this->root), &hash, hashDeleteComp); + found = TR_treeDelete(this->tree, &hash, hashDeleteComp); return found; } @@ -59,7 +59,7 @@ TR_hashDelete(TR_Hash this, const char * search, size_t nsearch) void * TR_hashDeleteByVal(TR_Hash this, unsigned long hash) { - void * found = TR_treeDelete(&(this->root), &hash, hashDeleteComp); + void * found = TR_treeDelete(this->tree, &hash, hashDeleteComp); return found; } diff --git a/src/hash/each.c b/src/hash/each.c index 97c3995..33f68b7 100644 --- a/src/hash/each.c +++ b/src/hash/each.c @@ -34,7 +34,7 @@ walk(const void * node, const void * data, const int depth) cb(node, data); } -void +unsigned long TR_hashEach( TR_Hash this, const void * data, @@ -42,7 +42,7 @@ TR_hashEach( { cb = callback; - TR_treeWalk(this->root, data, walk); + return TR_treeWalk(this->tree, data, walk); } // vim: set ts=4 sw=4: diff --git a/src/hash/get.c b/src/hash/get.c index fd439ca..e26cafa 100644 --- a/src/hash/get.c +++ b/src/hash/get.c @@ -52,7 +52,7 @@ void * TR_hashGet(TR_Hash this, const char * search, size_t nsearch) { unsigned long hash = TR_sdbm((const unsigned char *)search, nsearch); - void * found = TR_treeFind(this->root, &hash, hashGetComp); + void * found = TR_treeFind(this->tree, &hash, hashGetComp); return found; } @@ -60,7 +60,7 @@ TR_hashGet(TR_Hash this, const char * search, size_t nsearch) void * TR_hashGetByVal(TR_Hash this, unsigned long hash) { - void * found = TR_treeFind(this->root, &hash, hashGetComp); + void * found = TR_treeFind(this->tree, &hash, hashGetComp); return found; } diff --git a/src/hash/get_first.c b/src/hash/get_first.c index d378cc2..1d93689 100644 --- a/src/hash/get_first.c +++ b/src/hash/get_first.c @@ -27,7 +27,7 @@ void * TR_hashGetFirst(TR_Hash this) { - return this->root; + return this->tree->root; } // vim: set ts=4 sw=4: diff --git a/src/hash/hash.c b/src/hash/hash.c index 99773d0..3e3dbb3 100644 --- a/src/hash/hash.c +++ b/src/hash/hash.c @@ -31,6 +31,10 @@ static int hashCtor(void * _this, va_list * params) { + TR_Hash this = _this; + + this->tree = TR_new(TR_Tree); + return 0; } @@ -41,6 +45,8 @@ hashDtor(void * _this) TR_Hash this = _this; TR_hashCleanup(this); + + TR_delete(this->tree); } TR_INIT_IFACE(TR_Class, hashCtor, hashDtor, NULL); diff --git a/src/queue/Makefile.am b/src/queue/Makefile.am index d3e49c5..6d13c33 100644 --- a/src/queue/Makefile.am +++ b/src/queue/Makefile.am @@ -1,17 +1,13 @@ ACLOCAL_AMFLAGS = -I m4 AUTOMAKE_OPTIONS = subdir-objects -AM_CFLAGS += -I../../include/ +AM_CFLAGS += -I../../include/ -std=c99 -DREENTRANT -lpthread +AM_LDFLAGS += -lpthread -noinst_LTLIBRARIES = libqueue.la +QUEUE = queue.c get.c put.c put_first.c find.c find_parent.c delete.c destroy.c -libqueue_la_SOURCES = queue.c \ - get.c \ - put.c \ - put_first.c \ - find.c \ - find_parent.c \ - delete.c \ - destroy.c +noinst_LTLIBRARIES = libqueue.la +libqueue_la_SOURCES = $(QUEUE) libqueue_la_CFLAGS = $(AM_CFLAGS) +libqueue_la_LIBADD = $(AM_LDFLAGS) diff --git a/src/queue/delete.c b/src/queue/delete.c index d0676d6..c9ecc51 100644 --- a/src/queue/delete.c +++ b/src/queue/delete.c @@ -26,9 +26,13 @@ void TR_queueDelete(TR_Queue this, void * msg) { - TR_Queue node, parent = TR_queueFindParent(this, msg); + TR_Queue node, parent; + + parent = TR_queueFindParent(this, msg); - if (! parent) return; + if (! parent) { + return; + } node = parent->next; parent->next = node->next; diff --git a/src/queue/destroy.c b/src/queue/destroy.c index d70ae1f..d758e87 100644 --- a/src/queue/destroy.c +++ b/src/queue/destroy.c @@ -28,8 +28,10 @@ void TR_queueDestroy(TR_Queue this) { - TR_Queue node = this->first; + TR_Queue node; + node = this->first; + while (NULL != node) { TR_Queue next = node->next; if (this->free_msgs) { diff --git a/src/queue/put.c b/src/queue/put.c index 803958c..f5969c3 100644 --- a/src/queue/put.c +++ b/src/queue/put.c @@ -26,7 +26,9 @@ void TR_queuePut(TR_Queue this, void * msg) { - TR_Queue node = (this->last)? this->last : this; + TR_Queue node; + + node = (this->last)? this->last : this; node->next = TR_new(TR_Queue); this->last = node->next; diff --git a/src/queue/put_first.c b/src/queue/put_first.c index 80e3bf0..c52ea9d 100644 --- a/src/queue/put_first.c +++ b/src/queue/put_first.c @@ -26,7 +26,9 @@ void TR_queuePutFirst(TR_Queue this, void * msg) { - TR_Queue current_first = this->first; + TR_Queue current_first; + + current_first = this->first; this->first = this->next = TR_new(TR_Queue); this->first->next = current_first; diff --git a/src/queue/queue.c b/src/queue/queue.c index 29d0c81..79ec171 100644 --- a/src/queue/queue.c +++ b/src/queue/queue.c @@ -40,7 +40,9 @@ static void queueDtor(void * _this) { - TR_queueDestroy((TR_Queue)_this); + TR_Queue this = _this; + + TR_queueDestroy(this); } TR_INIT_IFACE(TR_Class, queueCtor, queueDtor, NULL); diff --git a/src/tree/Makefile.am b/src/tree/Makefile.am index e28e6ed..83aad30 100644 --- a/src/tree/Makefile.am +++ b/src/tree/Makefile.am @@ -1,16 +1,19 @@ ACLOCAL_AMFLAGS = -I m4 AUTOMAKE_OPTIONS = subdir-objects +AM_CFLAGS += -I../../include/ -std=c99 -DREENTRANT -lpthread +AM_LDFLAGS += -lpthread + TREE = tree.c \ + tree_node.c \ find.c \ insert.c \ delete.c \ walk.c \ destroy.c -AM_CFLAGS += -I../../include/ - noinst_LTLIBRARIES = libtree.la libtree_la_SOURCES = $(TREE) libtree_la_CFLAGS = $(AM_CFLAGS) +libtree_la_LIBADD = $(AM_LDFLAGS) diff --git a/src/tree/delete.c b/src/tree/delete.c index c23d44a..0275761 100644 --- a/src/tree/delete.c +++ b/src/tree/delete.c @@ -24,14 +24,15 @@ #include "tr/tree.h" void * -TR_treeDelete(TR_Tree * this, const void * search, TR_TreeComp comp) +TR_treeDelete(TR_Tree this, const void * search, TR_TreeComp comp) { - TR_Tree node = *this; - TR_Tree del_node; - TR_Tree sibling; - int found; + TR_TreeNode node; + TR_TreeNode del_node; + TR_TreeNode sibling; + int found; + void * data; - void * data; + node = this->root; TR_TREE_FIND(node, search, found, comp); @@ -57,7 +58,7 @@ TR_treeDelete(TR_Tree * this, const void * search, TR_TreeComp comp) * out inOrderSuccessor and remove the inOrderSuccessor. */ if (NULL != TR_TREE_LEFT(node) && NULL != TR_TREE_RIGHT(node)) { - TR_Tree successor; + TR_TreeNode successor; TR_TREE_INORDER_SUCC(node, successor); @@ -66,12 +67,12 @@ TR_treeDelete(TR_Tree * this, const void * search, TR_TreeComp comp) } { - TR_Tree child = TR_TREE_CHILD(node); + TR_TreeNode child = TR_TREE_CHILD(node); /* * if we still have one child replace ourself with it. */ - TR_TREE_REPLACE_NODE(this, node, child); + TR_TREE_REPLACE_NODE(&(this->root), node, child); /* * and finally delete the node...and prepare ourselfs @@ -105,9 +106,10 @@ TR_treeDelete(TR_Tree * this, const void * search, TR_TreeComp comp) * rebalancing process...(this does not make much sense, but * to be honest I don't know now.) */ - TR_TREE_BALANCE_DELETE(this, node, sibling); + TR_TREE_BALANCE_DELETE(&(this->root), node, sibling); TR_delete(del_node); + return data; } diff --git a/src/tree/destroy.c b/src/tree/destroy.c index 72c472f..204c5fb 100644 --- a/src/tree/destroy.c +++ b/src/tree/destroy.c @@ -24,12 +24,15 @@ #include "tr/tree.h" void -TR_treeDestroy(TR_Tree * this, TR_TreeAction action) +TR_treeDestroy(TR_Tree this, TR_TreeAction action) { - TR_Tree previous = * this; - TR_Tree node = * this; - int depth = 1; + TR_TreeNode previous; + TR_TreeNode node; + int depth = 1; + previous = this->root; + node = this->root; + /* * I think this has something like O(n+log(n)) on a ballanced * tree because I have to traverse back the rightmost leaf to @@ -44,7 +47,7 @@ TR_treeDestroy(TR_Tree * this, TR_TreeAction action) || previous == TR_TREE_LEFT(node)) && NULL == TR_TREE_RIGHT(node)) || previous == TR_TREE_RIGHT(node)) { - TR_Tree parent = TR_TREE_PARENT(node); + TR_TreeNode parent = TR_TREE_PARENT(node); if (action) { action(node->data, NULL, depth); @@ -82,7 +85,7 @@ TR_treeDestroy(TR_Tree * this, TR_TreeAction action) } } - *this = NULL; + this->root = NULL; } // vim: set ts=4 sw=4: diff --git a/src/tree/find.c b/src/tree/find.c index 694eab4..ad3a2a1 100644 --- a/src/tree/find.c +++ b/src/tree/find.c @@ -25,11 +25,15 @@ void * TR_treeFind(TR_Tree this, const void * search, TR_TreeComp comp) { - int found; + int found; + TR_TreeNode node; + void * retval; - TR_TREE_FIND(this, search, found, comp); + node = this->root; + TR_TREE_FIND(node, search, found, comp); + retval = found == 0 ? node->data : NULL; - return found == 0 ? this->data : NULL; + return retval; } // vim: set ts=4 sw=4: diff --git a/src/tree/insert.c b/src/tree/insert.c index 4ff8b08..56a98d0 100644 --- a/src/tree/insert.c +++ b/src/tree/insert.c @@ -24,11 +24,14 @@ #include "tr/tree.h" void * -TR_treeInsert(TR_Tree * this, const void * search, TR_TreeComp comp) +TR_treeInsert(TR_Tree this, const void * search, TR_TreeComp comp) { - TR_Tree node = *this; - TR_Tree new_node = NULL; - int found; + TR_TreeNode new_node = NULL; + TR_TreeNode node; + int found; + void * retval; + + node = this->root; /* * insert the node or return the one in tree if comparison @@ -39,7 +42,7 @@ TR_treeInsert(TR_Tree * this, const void * search, TR_TreeComp comp) * if the root is NULL we simple add the element and set * node to it. */ - *this = node = new_node = TR_new(TR_Tree, search); + this->root = node = new_node = TR_new(TR_TreeNode, search); } else { TR_TREE_FIND(node, search, found, comp); @@ -55,11 +58,11 @@ TR_treeInsert(TR_Tree * this, const void * search, TR_TreeComp comp) } else { // not found if (0 < found) { - node->left = TR_new(TR_Tree, search); + node->left = TR_new(TR_TreeNode, search); node->left->parent = node; node = new_node = node->left; } else { - node->right = TR_new(TR_Tree, search); + node->right = TR_new(TR_TreeNode, search); node->right->parent = node; node = new_node = node->right; } @@ -70,9 +73,10 @@ TR_treeInsert(TR_Tree * this, const void * search, TR_TreeComp comp) * we expect node not to be NULL and pointing to our * new node at this point...now rabalance the tree */ - TR_TREE_BALANCE_INSERT(this, node); + TR_TREE_BALANCE_INSERT(&(this->root), node); + retval = new_node->data; - return new_node->data; + return retval; } // vim: set ts=4 sw=4: diff --git a/src/tree/tree.c b/src/tree/tree.c index 7eeb635..9daf328 100644 --- a/src/tree/tree.c +++ b/src/tree/tree.c @@ -33,11 +33,7 @@ treeCtor(void * _this, va_list * params) { TR_Tree this = _this; - this->data = va_arg(*params, void *); - this->color = rbRed; - this->parent = NULL; - this->left = NULL; - this->right = NULL; + this->root = NULL; return 0; } diff --git a/src/tree/tree_node.c b/src/tree/tree_node.c new file mode 100644 index 0000000..1ac884a --- /dev/null +++ b/src/tree/tree_node.c @@ -0,0 +1,50 @@ +/** + * \file + * + * \author Georg Hopp + * + * \copyright + * Copyright © 2014 Georg Hopp + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#define _GNU_SOURCE + +#include + +#include "trbase.h" +#include "tr/tree.h" + +static +int +treeNodeCtor(void * _this, va_list * params) +{ + TR_TreeNode this = _this; + + this->data = va_arg(*params, void *); + this->color = rbRed; + this->parent = NULL; + this->left = NULL; + this->right = NULL; + + return 0; +} + +static void treeNodeDtor(void * _this) {} + +TR_INIT_IFACE(TR_Class, treeNodeCtor, treeNodeDtor, NULL); +TR_CREATE_CLASS(TR_TreeNode, NULL, NULL, TR_IF(TR_Class)); + +// vim: set ts=4 sw=4: diff --git a/src/tree/walk.c b/src/tree/walk.c index 72caff5..036b3ae 100644 --- a/src/tree/walk.c +++ b/src/tree/walk.c @@ -22,12 +22,16 @@ #include "tr/tree.h" -void +unsigned long TR_treeWalk(TR_Tree this, const void * data, TR_TreeAction action) { - TR_Tree previous = this; - TR_Tree node = this; - int depth = 1; + TR_TreeNode previous; + TR_TreeNode node; + int depth = 1; + unsigned long processed = 0; + + previous = this->root; + node = this->root; while (NULL != node) { if (previous == TR_TREE_RIGHT(node)) { @@ -40,6 +44,7 @@ TR_treeWalk(TR_Tree this, const void * data, TR_TreeAction action) if (NULL == TR_TREE_LEFT(node) || previous == TR_TREE_LEFT(node)) { if (action) { action(node->data, data, depth); + processed++; } previous = node; @@ -56,6 +61,8 @@ TR_treeWalk(TR_Tree this, const void * data, TR_TreeAction action) depth++; } } + + return processed; } // vim: set ts=4 sw=4: