From a9ab62351203679688e3b2fd8d4c9353631298e2 Mon Sep 17 00:00:00 2001 From: Marius Tolzmann Date: Mon, 23 Apr 2012 10:16:36 +0200 Subject: [PATCH 01/10] bee_tree: add new function print(key,data) to tree structure --- src/bee_tree.c | 7 +++++-- src/bee_tree.h | 2 ++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/bee_tree.c b/src/bee_tree.c index 64a5a47..e76471f 100644 --- a/src/bee_tree.c +++ b/src/bee_tree.c @@ -240,7 +240,7 @@ static void bee_node_print(struct bee_tree *tree, struct bee_subtree *node, int assert(tree); assert(node); - assert(tree->print_key); + assert(tree->print || tree->print_key); for (i = 0 ; i < depth ; i++) { putchar('-'); @@ -252,7 +252,10 @@ static void bee_node_print(struct bee_tree *tree, struct bee_subtree *node, int if(dir < 0) putchar('/'); - tree->print_key(node->key); + if (tree->print) + tree->print(node->key, node->data); + else + tree->print_key(node->key); #ifdef TREE_DEBUG printf(" [ h=%d bf=%d ]", node->height, node->balance_factor); diff --git a/src/bee_tree.h b/src/bee_tree.h index 39a88d8..069c6c4 100644 --- a/src/bee_tree.h +++ b/src/bee_tree.h @@ -11,7 +11,9 @@ struct bee_tree { void (*free_key)(void *data); int (*compare_key)(void *a, void *b); + void (*print_key)(void *key); + void (*print)(void *key, void *data); }; struct bee_subtree { From 3eb2fe615d26c33b5c9f31998940c4f5fc136dc1 Mon Sep 17 00:00:00 2001 From: Marius Tolzmann Date: Mon, 23 Apr 2012 10:32:31 +0200 Subject: [PATCH 02/10] bee_tree: add flags variable to tree structure and bee_tree_set/unset_flags(..) functions --- src/bee_tree.c | 26 ++++++++++++++++++++++++++ src/bee_tree.h | 5 +++++ 2 files changed, 31 insertions(+) diff --git a/src/bee_tree.c b/src/bee_tree.c index e76471f..1fd9131 100644 --- a/src/bee_tree.c +++ b/src/bee_tree.c @@ -518,6 +518,32 @@ static void bee_subtree_print_plain(struct bee_tree *tree, struct bee_subtree *n bee_subtree_print_plain(tree, node->right); } +int bee_tree_set_flags(struct bee_tree *tree, int flags) +{ + int oflags; + + assert(tree); + assert(flags); + + oflags = tree->flags; + tree->flags |= flags; + + return oflags; +} + +int bee_tree_unset_flags(struct bee_tree *tree, int flags) +{ + int oflags; + + assert(tree); + assert(flags); + + oflags = tree->flags; + tree->flags &= ~flags; + + return oflags; +} + void bee_tree_print(struct bee_tree *tree) { assert(tree); diff --git a/src/bee_tree.h b/src/bee_tree.h index 069c6c4..185a062 100644 --- a/src/bee_tree.h +++ b/src/bee_tree.h @@ -5,6 +5,8 @@ struct bee_tree { struct bee_subtree *root; + int flags; + void (*free_data)(void *data); void * (*generate_key)(void *data); @@ -41,4 +43,7 @@ void *bee_tree_delete(struct bee_tree *tree, void *key); void bee_tree_print(struct bee_tree *tree); void bee_tree_print_plain(struct bee_tree *tree); +int bee_tree_set_flags(struct bee_tree *tree, int flags); +int bee_tree_unset_flags(struct bee_tree *tree, int flags); + #endif From dfd6706bb44fb484c7c534252f23ef8b089a1855 Mon Sep 17 00:00:00 2001 From: Marius Tolzmann Date: Mon, 23 Apr 2012 11:03:15 +0200 Subject: [PATCH 03/10] bee_tree: add support for uniqueness of tree nodes to enable dupe prevention set one of the flags below: BEE_TREE_FLAG_UNIQUE - unique keys do not insert dupes BEE_TREE_FLAG_UNIQUE_DATA - unique keys and data do not insert dupes - if key is already in tree also check data. tree->compare_data() must be set. data comparison is only used to prevent dupes and is not used to insert sorted or to find nodes bee_tree_insert(..) will return NULL if memory allocation fails or if the element is already in the tree. If memory allocation fails errno will be set to ENOMEM. If the element is already in the tree, errno will be set to EEXIST and the generated key will be freed using the free_key() tree-functions (if set). --- src/bee_tree.c | 25 +++++++++++++++++++++++-- src/bee_tree.h | 4 ++++ 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/src/bee_tree.c b/src/bee_tree.c index 1fd9131..4f0ef88 100644 --- a/src/bee_tree.c +++ b/src/bee_tree.c @@ -3,6 +3,7 @@ #include #include #include +#include #include "bee_tree.h" @@ -321,6 +322,19 @@ static struct bee_subtree *bee_tree_insert_node(struct bee_tree *tree, struct be while (!node->parent) { cmp = tree->compare_key(node->key, current->key); + if ((cmp == 0) && (tree->flags & (BEE_TREE_FLAG_UNIQUE|BEE_TREE_FLAG_UNIQUE_DATA))) { + /* do not insert dupes */ + if (!(tree->flags & BEE_TREE_FLAG_UNIQUE_DATA)) + return NULL; + + assert(tree->compare_data); + + cmp = tree->compare_data(node->data, current->data); + + if (cmp == 0) + return NULL; + } + if (cmp < 0) { if (current->left) { current = current->left; @@ -362,9 +376,16 @@ struct bee_subtree *bee_tree_insert(struct bee_tree *tree, void *data) node->data = data; node->key = tree->generate_key(data); - bee_tree_insert_node(tree, node); + if(bee_tree_insert_node(tree, node)) + return node; - return node; + if (tree->free_key) + tree->free_key(node->key); + + free(node); + + errno=EEXIST; + return NULL; } static struct bee_subtree *bee_tree_search_node_by_key(struct bee_tree *tree, void *key) diff --git a/src/bee_tree.h b/src/bee_tree.h index 185a062..1e52a5c 100644 --- a/src/bee_tree.h +++ b/src/bee_tree.h @@ -13,6 +13,7 @@ struct bee_tree { void (*free_key)(void *data); int (*compare_key)(void *a, void *b); + int (*compare_data)(void *a, void *b); void (*print_key)(void *key); void (*print)(void *key, void *data); @@ -33,6 +34,9 @@ struct bee_subtree { #define BEE_TREE_MAX(a,b) (((a) > (b)) ? (a) : (b)) #define BEE_TREE_HEIGHT(t) ((t) ? ((t)->height) : 0) +#define BEE_TREE_FLAG_UNIQUE (1<<0) +#define BEE_TREE_FLAG_UNIQUE_DATA (1<<1) + struct bee_tree *bee_tree_allocate(void); void bee_tree_free(struct bee_tree *tree); struct bee_subtree *bee_tree_insert(struct bee_tree *tree, void *data); From a58e794309e34d13465276dd977d888753ef7cb7 Mon Sep 17 00:00:00 2001 From: Marius Tolzmann Date: Mon, 23 Apr 2012 11:22:43 +0200 Subject: [PATCH 04/10] beesort: use tree->print instead of tree->print_key --- src/beesort.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/beesort.c b/src/beesort.c index 8553a5c..57cc61f 100644 --- a/src/beesort.c +++ b/src/beesort.c @@ -48,9 +48,9 @@ int my_compare_key(void *a, void *b) return compare_beepackages(a, b); } -void my_print_key(void *key) +void my_print(void *key, void *data) { - print_format("%A", key, NULL); + print_format("%A", data, NULL); } struct bee_tree *init_tree(void) @@ -66,7 +66,7 @@ struct bee_tree *init_tree(void) tree->free_data = &my_free_data; tree->compare_key = &my_compare_key; - tree->print_key = &my_print_key; + tree->print = &my_print; return tree; } From 3d1284989908a456d377b1133d6fce7756f3a26f Mon Sep 17 00:00:00 2001 From: Marius Tolzmann Date: Mon, 23 Apr 2012 11:51:50 +0200 Subject: [PATCH 05/10] beesort: let bee_tree handle dupes --- src/beesort.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/beesort.c b/src/beesort.c index 57cc61f..b9e86fb 100644 --- a/src/beesort.c +++ b/src/beesort.c @@ -129,6 +129,9 @@ int main(int argc, char *argv[]) tree = init_tree(); + if (opt_uniq) + bee_tree_set_flags(tree, BEE_TREE_FLAG_UNIQUE); + while(fgets(line, LINE_MAX, file)) { l = strlen(line); s = line; @@ -157,8 +160,7 @@ int main(int argc, char *argv[]) v->pkgname = v->string; } - if(!(opt_uniq && bee_tree_search(tree, v))) - bee_tree_insert(tree, v); + bee_tree_insert(tree, v); } fclose(file); From 1883293aa1b3f618742b766158dbd64fff791c18 Mon Sep 17 00:00:00 2001 From: Marius Tolzmann Date: Mon, 23 Apr 2012 11:58:18 +0200 Subject: [PATCH 06/10] bee_tree: if key generation in bee_tree_insert fails, return NULL make sure to set errno to something useful in generate_key. Do not use EEXIST since this is reserved for dupe prevention. --- src/bee_tree.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/bee_tree.c b/src/bee_tree.c index 4f0ef88..9753355 100644 --- a/src/bee_tree.c +++ b/src/bee_tree.c @@ -369,6 +369,8 @@ struct bee_subtree *bee_tree_insert(struct bee_tree *tree, void *data) assert(tree->generate_key); + errno = 0; + node = bee_subtree_allocate(); if (!node) return NULL; @@ -376,6 +378,11 @@ struct bee_subtree *bee_tree_insert(struct bee_tree *tree, void *data) node->data = data; node->key = tree->generate_key(data); + if (!node->key) { + free(node); + return NULL; + } + if(bee_tree_insert_node(tree, node)) return node; From cf6a2d9af50a2cae56a61d9f2bd212db5ce4671f Mon Sep 17 00:00:00 2001 From: Marius Tolzmann Date: Mon, 23 Apr 2012 12:41:09 +0200 Subject: [PATCH 07/10] bee_tree: fix prototype of generate_key --- src/bee_tree.c | 4 ++-- src/bee_tree.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/bee_tree.c b/src/bee_tree.c index 9753355..abb84ef 100644 --- a/src/bee_tree.c +++ b/src/bee_tree.c @@ -7,11 +7,11 @@ #include "bee_tree.h" -static void *bee_tree_generate_key_default(void *data) +static void *bee_tree_generate_key_default(const void *data) { assert(data); - return data; + return (void *)data; } static int bee_tree_compare_key_default(void *a, void *b) diff --git a/src/bee_tree.h b/src/bee_tree.h index 1e52a5c..d1aee66 100644 --- a/src/bee_tree.h +++ b/src/bee_tree.h @@ -9,8 +9,8 @@ struct bee_tree { void (*free_data)(void *data); - void * (*generate_key)(void *data); - void (*free_key)(void *data); + void * (*generate_key)(const void *data); + void (*free_key)(void *key); int (*compare_key)(void *a, void *b); int (*compare_data)(void *a, void *b); From 5fa8423bf023b9865da69b7bbe1aa5711133fd4b Mon Sep 17 00:00:00 2001 From: Marius Tolzmann Date: Mon, 23 Apr 2012 14:33:53 +0200 Subject: [PATCH 08/10] beesort: use bee_tree as intended (fixes several bugs) --- src/bee_tree.c | 1 - src/beesort.c | 120 ++++++++++++++++++++++++++++++++++++------------- 2 files changed, 88 insertions(+), 33 deletions(-) diff --git a/src/bee_tree.c b/src/bee_tree.c index abb84ef..53b6167 100644 --- a/src/bee_tree.c +++ b/src/bee_tree.c @@ -262,7 +262,6 @@ static void bee_node_print(struct bee_tree *tree, struct bee_subtree *node, int printf(" [ h=%d bf=%d ]", node->height, node->balance_factor); #endif - putchar('\n'); } static void bee_tree_balance_node(struct bee_tree *tree, struct bee_subtree *node) diff --git a/src/beesort.c b/src/beesort.c index b9e86fb..b848a9a 100644 --- a/src/beesort.c +++ b/src/beesort.c @@ -27,6 +27,7 @@ #include #include #include +#include #include "bee_version.h" #include "bee_version_compare.h" @@ -35,22 +36,81 @@ #include "bee_tree.h" #include "bee_getopt.h" -void my_free_data(void *data) +void my_free_key(void *key) { - struct beeversion *v = data; + struct beeversion *v = key; free(v->string); free(v); } +void my_free_data(void *data) +{ + free(data); +} + int my_compare_key(void *a, void *b) { return compare_beepackages(a, b); } +int my_compare_data(void *a, void *b) +{ + return strcmp(a, b); +} + void my_print(void *key, void *data) { - print_format("%A", data, NULL); + fputs(data, stdout); +} + +void *my_generate_key(const void *data) +{ + const char *line = data; + size_t l; + char *s, *p; + char *string; + struct beeversion *v; + + string = strdup(line); + + if(!string) { + perror("calloc(s)"); + return NULL; + } + + s = string; + l = strlen(s); + p = s+l-1; + + while (p > s && (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\r')) + *(p--) = 0; + + while (*s && (*s == ' ' || *s == '\t')) + s++; + + if(p < s) { + free(string); + errno = EINVAL; + return NULL; + } + + v = calloc(1, sizeof(*v)); + if(!v) { + perror("calloc(beeversion)"); + free(s); + return NULL; + } + + if(parse_version(s, v) != 0) { + free(v->string); + init_version(s, v); + v->pkgname = v->string; + } + + free(string); + + return v; } struct bee_tree *init_tree(void) @@ -64,9 +124,12 @@ struct bee_tree *init_tree(void) exit(EXIT_FAILURE); } - tree->free_data = &my_free_data; - tree->compare_key = &my_compare_key; - tree->print = &my_print; + tree->generate_key = &my_generate_key; + tree->free_key = &my_free_key; + tree->free_data = &my_free_data; + tree->compare_key = &my_compare_key; + tree->compare_data = &my_compare_data; + tree->print = &my_print; return tree; } @@ -74,15 +137,15 @@ struct bee_tree *init_tree(void) int main(int argc, char *argv[]) { - char line[LINE_MAX], *s, *p; + char line[LINE_MAX]; + char *data; FILE *file; + struct bee_tree *tree; - struct beeversion *v; + struct bee_subtree *subtree; char *filename; - int l; - int opt; int optindex; int optind; @@ -133,34 +196,27 @@ int main(int argc, char *argv[]) bee_tree_set_flags(tree, BEE_TREE_FLAG_UNIQUE); while(fgets(line, LINE_MAX, file)) { - l = strlen(line); - s = line; - p = line+l-1; - - while (p > s && (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\r')) - *(p--) = 0; - - while (*s && (*s == ' ' || *s == '\t')) - s++; - - if(p < s) - continue; - - v = calloc(1, sizeof(*v)); - if(v == NULL) { - perror("cannot allocate memory .."); + data = strdup(line); + if(!data) { + perror("strdup(data)"); bee_tree_free(tree); fclose(file); exit(EXIT_FAILURE); } - if(parse_version(s, v) != 0) { - free(v->string); - init_version(s, v); - v->pkgname = v->string; - } + subtree = bee_tree_insert(tree, data); + if(subtree) + continue; - bee_tree_insert(tree, v); + if(errno == EINVAL) + continue; + + if(errno == EEXIST) + continue; + + bee_tree_free(tree); + fclose(file); + exit(EXIT_FAILURE); } fclose(file); From 3fe2c8f53439947d5ad69ab3f01184b835770db2 Mon Sep 17 00:00:00 2001 From: Marius Tolzmann Date: Mon, 23 Apr 2012 15:01:50 +0200 Subject: [PATCH 09/10] beesort: allow --uniq to be used more then once --uniq (used once): output only the first of equal lines --uniq --uniq (used at least twice) output each calculated bee-package-version only once (no matter how the line looks like, if two lines result in the same beeversioning only the first is printed) --- src/beesort.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/beesort.c b/src/beesort.c index b848a9a..c622c85 100644 --- a/src/beesort.c +++ b/src/beesort.c @@ -170,10 +170,11 @@ int main(int argc, char *argv[]) switch(opt) { case 'u': - opt_uniq = 1; + opt_uniq++; break; } } + optind = optctl.optind; argc = optctl.argc; argv = optctl.argv; @@ -192,7 +193,9 @@ int main(int argc, char *argv[]) tree = init_tree(); - if (opt_uniq) + if (opt_uniq == 1) + bee_tree_set_flags(tree, BEE_TREE_FLAG_UNIQUE_DATA); + else if (opt_uniq > 1) bee_tree_set_flags(tree, BEE_TREE_FLAG_UNIQUE); while(fgets(line, LINE_MAX, file)) { From b794d2682f78a7873e184c5775125c9e9d4f6a5e Mon Sep 17 00:00:00 2001 From: Marius Tolzmann Date: Mon, 23 Apr 2012 15:20:50 +0200 Subject: [PATCH 10/10] Revert "bee-list: fix bee list -a --display-pathname" This reverts commit 53349ce237b1639af037855c1e39d4043e8c81f2. beesort is fixed now 8) --- src/bee-list.sh.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bee-list.sh.in b/src/bee-list.sh.in index 4d1b1f9..cbbb3a0 100644 --- a/src/bee-list.sh.in +++ b/src/bee-list.sh.in @@ -43,7 +43,7 @@ fi VERSION=${BEE_VERSION} : ${BEE_BINDIR:=@BINDIR@} -: ${BEESORT:=sort} +: ${BEESORT:=${BEE_BINDIR}/beesort} # # BUGS TO FIX/FEATURES TO ADD: