| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156 |
- /*
- * Copyright (C) 2000,2001 Florian Sander
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
- #define GENERIC_LINKED_LIST
- struct llist_entry
- {
- struct llist_entry *next;
- struct llist_entry *last;
- void *data;
- };
- struct llist_header
- {
- struct llist_entry *root;
- struct llist_entry *last;
- int size;
- int (*comparedata) (void *, void *);
- int (*expmemdata) (void *);
- void (*freedata) (void *);
- };
- static void llist_append(struct llist_header *head, void *data)
- {
- struct llist_entry *p, *np;
- np = nmalloc(sizeof(struct llist_entry));
- np->data = NULL;
- np->next = NULL;
- np->last = NULL;
- np->data = data;
- for (p = head->root; p && p->next; p = p->next);
- if (p) {
- p->next = np;
- np->last = p;
- } else
- head->root = np;
- head->size++;
- }
- static void *llist_find(struct llist_header *head, void *key)
- {
- struct llist_entry *p;
- for (p = head->root; p; p = p->next)
- if (head->comparedata(p->data, key))
- return p->data;
- return NULL;
- }
- static void llist_delete(struct llist_header *head, void *key)
- {
- struct llist_entry *p, *last;
- p = head->root;
- last = NULL;
- while (p) {
- if (head->comparedata(p->data, key)) {
- if (last)
- last->next = p->next;
- else
- head->root = p->next;
- head->freedata(p->data);
- if (p->next)
- p->next->last = last;
- /* make sure that the getfirst/getnext-loop can
- * continue if we are deleting the currently active
- * item. If last is NULL, then getnext() will continue
- * with the root which should be the correct successor
- * of p in this case. */
- if (head->last == p)
- head->last = last;
- nfree(p);
- if (last)
- p = last->next;
- else
- p = head->root;
- head->size--;
- } else {
- last = p;
- p = p->next;
- }
- }
- }
- static int llist_expmem(struct llist_header *head)
- {
- struct llist_entry *p;
- int size = 0;
- for (p = head->root; p; p = p->next) {
- size += sizeof(struct llist_entry);
- size += head->expmemdata(p->data);
- }
- return size;
- }
- static void llist_free(struct llist_header *head)
- {
- struct llist_entry *p, *n;
- p = head->root;
- while (p) {
- n = p->next;
- head->freedata(p->data);
- nfree(p);
- p = n;
- }
- head->root = NULL;
- head->size = 0;
- }
- static struct llist_entry *llist_getfirst(struct llist_header *head)
- {
- Assert(head);
- head->last = head->root;
- if (head->last)
- return head->last->data;
- else
- return NULL;
- }
- static struct llist_entry *llist_getnext(struct llist_header *head)
- {
- /* if head->last exists, then we can just proceed to the next
- * entry. If it does not exist, then it was the first entry in
- * the chain and got deleted while we were looping, so we can
- * simply proceed with the root which should be the next item. */
- if (head->last)
- head->last = head->last->next;
- else
- head->last = head->root;
- if (head->last)
- return head->last->data;
- else
- return NULL;
- }
|