/* 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 ** Campus Information Technologies and Educational Services ** University of Illinois at Urbana-Champaign */ #include #include #include #include #include #include #ifdef STDC_HEADERS # include # include #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; }