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: diff --git a/src/bee_tree.c b/src/bee_tree.c index 64a5a47..53b6167 100644 --- a/src/bee_tree.c +++ b/src/bee_tree.c @@ -3,14 +3,15 @@ #include #include #include +#include #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) @@ -240,7 +241,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,13 +253,15 @@ 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); #endif - putchar('\n'); } static void bee_tree_balance_node(struct bee_tree *tree, struct bee_subtree *node) @@ -318,6 +321,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; @@ -352,6 +368,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; @@ -359,9 +377,21 @@ 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 (!node->key) { + free(node); + return NULL; + } - return node; + if(bee_tree_insert_node(tree, 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) @@ -515,6 +545,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 39a88d8..d1aee66 100644 --- a/src/bee_tree.h +++ b/src/bee_tree.h @@ -5,13 +5,18 @@ struct bee_tree { struct bee_subtree *root; + int flags; + 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); + void (*print_key)(void *key); + void (*print)(void *key, void *data); }; struct bee_subtree { @@ -29,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); @@ -39,4 +47,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 diff --git a/src/beesort.c b/src/beesort.c index 8553a5c..c622c85 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); } -void my_print_key(void *key) +int my_compare_data(void *a, void *b) { - print_format("%A", key, NULL); + return strcmp(a, b); +} + +void my_print(void *key, void *data) +{ + 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_key = &my_print_key; + 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; @@ -107,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; @@ -129,36 +193,33 @@ int main(int argc, char *argv[]) tree = init_tree(); - 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 (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); - if(p < s) - continue; - - v = calloc(1, sizeof(*v)); - if(v == NULL) { - perror("cannot allocate memory .."); + while(fgets(line, LINE_MAX, file)) { + 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; - if(!(opt_uniq && bee_tree_search(tree, v))) - bee_tree_insert(tree, v); + if(errno == EINVAL) + continue; + + if(errno == EEXIST) + continue; + + bee_tree_free(tree); + fclose(file); + exit(EXIT_FAILURE); } fclose(file);