diff options
Diffstat (limited to 'libtar/libtar_list.c')
-rw-r--r-- | libtar/libtar_list.c | 458 |
1 files changed, 458 insertions, 0 deletions
diff --git a/libtar/libtar_list.c b/libtar/libtar_list.c new file mode 100644 index 000000000..2c5febb01 --- /dev/null +++ b/libtar/libtar_list.c @@ -0,0 +1,458 @@ +/* listhash/libtar_list.c. Generated from list.c.in by configure. */ + +/* +** Copyright 1998-2002 University of Illinois Board of Trustees +** Copyright 1998-2002 Mark D. Roth +** All rights reserved. +** +** libtar_list.c - linked list routines +** +** Mark D. Roth <roth@uiuc.edu> +** Campus Information Technologies and Educational Services +** University of Illinois at Urbana-Champaign +*/ + +#include <config.h> +#include <compat.h> + +#include <libtar_listhash.h> + +#include <stdio.h> +#include <errno.h> +#include <sys/param.h> + +#ifdef STDC_HEADERS +# include <string.h> +# include <stdlib.h> +#endif + + +/* +** libtar_listptr_reset() - reset a list pointer +*/ +void +libtar_listptr_reset(libtar_listptr_t *lp) +{ + *lp = NULL; +} + + +/* +** libtar_listptr_data() - retrieve the data pointed to by lp +*/ +void * +libtar_listptr_data(libtar_listptr_t *lp) +{ + return (*lp)->data; +} + + +/* +** libtar_list_new() - create a new, empty list +*/ +libtar_list_t * +libtar_list_new(int flags, libtar_cmpfunc_t cmpfunc) +{ + libtar_list_t *newlist; + +#ifdef DS_DEBUG + printf("in libtar_list_new(%d, 0x%lx)\n", flags, cmpfunc); +#endif + + if (flags != LIST_USERFUNC + && flags != LIST_STACK + && flags != LIST_QUEUE) + { + errno = EINVAL; + return NULL; + } + + newlist = (libtar_list_t *)calloc(1, sizeof(libtar_list_t)); + if (cmpfunc != NULL) + newlist->cmpfunc = cmpfunc; + else + newlist->cmpfunc = (libtar_cmpfunc_t)strcmp; + newlist->flags = flags; + + return newlist; +} + + +/* +** libtar_list_iterate() - call a function for every element +** in a list +*/ +int +libtar_list_iterate(libtar_list_t *l, + libtar_iterate_func_t plugin, + void *state) +{ + libtar_listptr_t n; + + if (l == NULL) + return -1; + + for (n = l->first; n != NULL; n = n->next) + { + if ((*plugin)(n->data, state) == -1) + return -1; + } + + return 0; +} + + +/* +** libtar_list_empty() - empty the list +*/ +void +libtar_list_empty(libtar_list_t *l, libtar_freefunc_t freefunc) +{ + libtar_listptr_t n; + + for (n = l->first; n != NULL; n = l->first) + { + l->first = n->next; + if (freefunc != NULL) + (*freefunc)(n->data); + free(n); + } + + l->nents = 0; +} + + +/* +** libtar_list_free() - remove and free() the whole list +*/ +void +libtar_list_free(libtar_list_t *l, libtar_freefunc_t freefunc) +{ + libtar_list_empty(l, freefunc); + free(l); +} + + +/* +** libtar_list_nents() - return number of elements in the list +*/ +unsigned int +libtar_list_nents(libtar_list_t *l) +{ + return l->nents; +} + + +/* +** libtar_list_add() - adds an element to the list +** returns: +** 0 success +** -1 (and sets errno) failure +*/ +int +libtar_list_add(libtar_list_t *l, void *data) +{ + libtar_listptr_t n, m; + +#ifdef DS_DEBUG + printf("==> libtar_list_add(\"%s\")\n", (char *)data); +#endif + + n = (libtar_listptr_t)malloc(sizeof(struct libtar_node)); + if (n == NULL) + return -1; + n->data = data; + l->nents++; + +#ifdef DS_DEBUG + printf(" libtar_list_add(): allocated data\n"); +#endif + + /* if the list is empty */ + if (l->first == NULL) + { + l->last = l->first = n; + n->next = n->prev = NULL; +#ifdef DS_DEBUG + printf("<== libtar_list_add(): list was empty; " + "added first element and returning 0\n"); +#endif + return 0; + } + +#ifdef DS_DEBUG + printf(" libtar_list_add(): list not empty\n"); +#endif + + if (l->flags == LIST_STACK) + { + n->prev = NULL; + n->next = l->first; + if (l->first != NULL) + l->first->prev = n; + l->first = n; +#ifdef DS_DEBUG + printf("<== libtar_list_add(): LIST_STACK set; " + "added in front\n"); +#endif + return 0; + } + + if (l->flags == LIST_QUEUE) + { + n->prev = l->last; + n->next = NULL; + if (l->last != NULL) + l->last->next = n; + l->last = n; +#ifdef DS_DEBUG + printf("<== libtar_list_add(): LIST_QUEUE set; " + "added at end\n"); +#endif + return 0; + } + + for (m = l->first; m != NULL; m = m->next) + if ((*(l->cmpfunc))(data, m->data) < 0) + { + /* + ** if we find one that's bigger, + ** insert data before it + */ +#ifdef DS_DEBUG + printf(" libtar_list_add(): gotcha..." + "inserting data\n"); +#endif + if (m == l->first) + { + l->first = n; + n->prev = NULL; + m->prev = n; + n->next = m; +#ifdef DS_DEBUG + printf("<== libtar_list_add(): " + "added first, returning 0\n"); +#endif + return 0; + } + m->prev->next = n; + n->prev = m->prev; + m->prev = n; + n->next = m; +#ifdef DS_DEBUG + printf("<== libtar_list_add(): added middle," + " returning 0\n"); +#endif + return 0; + } + +#ifdef DS_DEBUG + printf(" libtar_list_add(): new data larger than current " + "list elements\n"); +#endif + + /* if we get here, data is bigger than everything in the list */ + l->last->next = n; + n->prev = l->last; + l->last = n; + n->next = NULL; +#ifdef DS_DEBUG + printf("<== libtar_list_add(): added end, returning 0\n"); +#endif + return 0; +} + + +/* +** libtar_list_del() - remove the element pointed to by n +** from the list l +*/ +void +libtar_list_del(libtar_list_t *l, libtar_listptr_t *n) +{ + libtar_listptr_t m; + +#ifdef DS_DEBUG + printf("==> libtar_list_del()\n"); +#endif + + l->nents--; + + m = (*n)->next; + + if ((*n)->prev) + (*n)->prev->next = (*n)->next; + else + l->first = (*n)->next; + if ((*n)->next) + (*n)->next->prev = (*n)->prev; + else + l->last = (*n)->prev; + + free(*n); + *n = m; +} + + +/* +** libtar_list_next() - get the next element in the list +** returns: +** 1 success +** 0 end of list +*/ +int +libtar_list_next(libtar_list_t *l, + libtar_listptr_t *n) +{ + if (*n == NULL) + *n = l->first; + else + *n = (*n)->next; + + return (*n != NULL ? 1 : 0); +} + + +/* +** libtar_list_prev() - get the previous element in the list +** returns: +** 1 success +** 0 end of list +*/ +int +libtar_list_prev(libtar_list_t *l, + libtar_listptr_t *n) +{ + if (*n == NULL) + *n = l->last; + else + *n = (*n)->prev; + + return (*n != NULL ? 1 : 0); +} + + +/* +** libtar_str_match() - string matching function +** returns: +** 1 match +** 0 no match +*/ +int +libtar_str_match(char *check, char *data) +{ + return !strcmp(check, data); +} + + +/* +** libtar_list_add_str() - splits string str into delim-delimited +** elements and adds them to list l +** returns: +** 0 success +** -1 (and sets errno) failure +*/ +int +libtar_list_add_str(libtar_list_t *l, + char *str, char *delim) +{ + char tmp[10240]; + char *tokp, *nextp = tmp; + + strlcpy(tmp, str, sizeof(tmp)); + while ((tokp = strsep(&nextp, delim)) != NULL) + { + if (*tokp == '\0') + continue; + if (libtar_list_add(l, strdup(tokp))) + return -1; + } + + return 0; +} + + +/* +** libtar_list_search() - find an entry in a list +** returns: +** 1 match found +** 0 no match +*/ +int +libtar_list_search(libtar_list_t *l, + libtar_listptr_t *n, void *data, + libtar_matchfunc_t matchfunc) +{ +#ifdef DS_DEBUG + printf("==> libtar_list_search(l=0x%lx, n=0x%lx, \"%s\")\n", + l, n, (char *)data); +#endif + + if (matchfunc == NULL) + matchfunc = (libtar_matchfunc_t)libtar_str_match; + + if (*n == NULL) + *n = l->first; + else + *n = (*n)->next; + + for (; *n != NULL; *n = (*n)->next) + { +#ifdef DS_DEBUG + printf("checking against \"%s\"\n", (char *)(*n)->data); +#endif + if ((*(matchfunc))(data, (*n)->data) != 0) + return 1; + } + +#ifdef DS_DEBUG + printf("no matches found\n"); +#endif + return 0; +} + + +/* +** libtar_list_dup() - copy an existing list +*/ +libtar_list_t * +libtar_list_dup(libtar_list_t *l) +{ + libtar_list_t *newlist; + libtar_listptr_t n; + + newlist = libtar_list_new(l->flags, l->cmpfunc); + for (n = l->first; n != NULL; n = n->next) + libtar_list_add(newlist, n->data); + +#ifdef DS_DEBUG + printf("returning from libtar_list_dup()\n"); +#endif + return newlist; +} + + +/* +** libtar_list_merge() - merge two lists into a new list +*/ +libtar_list_t * +libtar_list_merge(libtar_cmpfunc_t cmpfunc, int flags, + libtar_list_t *list1, + libtar_list_t *list2) +{ + libtar_list_t *newlist; + libtar_listptr_t n; + + newlist = libtar_list_new(flags, cmpfunc); + + n = NULL; + while (libtar_list_next(list1, &n) != 0) + libtar_list_add(newlist, n->data); + n = NULL; + while (libtar_list_next(list2, &n) != 0) + libtar_list_add(newlist, n->data); + + return newlist; +} + + |