summaryrefslogtreecommitdiffstats
path: root/libtar/libtar_list.c
diff options
context:
space:
mode:
Diffstat (limited to 'libtar/libtar_list.c')
-rw-r--r--libtar/libtar_list.c458
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;
+}
+
+