summaryrefslogtreecommitdiff
path: root/src/list.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/list.c')
-rw-r--r--src/list.c277
1 files changed, 277 insertions, 0 deletions
diff --git a/src/list.c b/src/list.c
new file mode 100644
index 0000000..2850d46
--- /dev/null
+++ b/src/list.c
@@ -0,0 +1,277 @@
+/*
+ * ircd-hybrid: an advanced Internet Relay Chat Daemon(ircd).
+ * list.c: Various assorted functions for various structures.
+ *
+ * Copyright (C) 2002 by the past and present ircd coders, and others.
+ *
+ * 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
+ *
+ * $Id$
+ */
+
+#include "stdinc.h"
+#include "list.h"
+#include "balloc.h"
+
+static BlockHeap *dnode_heap;
+
+
+/* init_dlink_nodes()
+ *
+ * inputs - NONE
+ * output - NONE
+ * side effects - initializes the dnode BlockHeap
+ */
+void
+init_dlink_nodes(void)
+{
+ dnode_heap = BlockHeapCreate("dlink node", sizeof(dlink_node), DNODE_HEAP_SIZE);
+}
+
+/* make_dlink_node()
+ *
+ * inputs - NONE
+ * output - pointer to new dlink_node
+ * side effects - NONE
+ */
+dlink_node *
+make_dlink_node(void)
+{
+ dlink_node *lp = BlockHeapAlloc(dnode_heap);
+
+ return lp;
+}
+
+/* free_dlink_node()
+ *
+ * inputs - pointer to dlink_node
+ * output - NONE
+ * side effects - free given dlink_node
+ */
+void
+free_dlink_node(dlink_node *ptr)
+{
+ BlockHeapFree(dnode_heap, ptr);
+}
+
+/*
+ * dlink_ routines are stolen from squid, except for dlinkAddBefore,
+ * which is mine.
+ * -- adrian
+ */
+void
+dlinkAdd(void *data, dlink_node *m, dlink_list *list)
+{
+ m->data = data;
+ m->prev = NULL;
+ m->next = list->head;
+
+ /* Assumption: If list->tail != NULL, list->head != NULL */
+ if (list->head != NULL)
+ list->head->prev = m;
+ else if (list->tail == NULL)
+ list->tail = m;
+
+ list->head = m;
+ list->length++;
+}
+
+void
+dlinkAddBefore(dlink_node *b, void *data, dlink_node *m, dlink_list *list)
+{
+ /* Shortcut - if its the first one, call dlinkAdd only */
+ if (b == list->head)
+ dlinkAdd(data, m, list);
+ else
+ {
+ m->data = data;
+ b->prev->next = m;
+ m->prev = b->prev;
+ b->prev = m;
+ m->next = b;
+ list->length++;
+ }
+}
+
+void
+dlinkAddTail(void *data, dlink_node *m, dlink_list *list)
+{
+ m->data = data;
+ m->next = NULL;
+ m->prev = list->tail;
+
+ /* Assumption: If list->tail != NULL, list->head != NULL */
+ if (list->tail != NULL)
+ list->tail->next = m;
+ else if (list->head == NULL)
+ list->head = m;
+
+ list->tail = m;
+ list->length++;
+}
+
+/* Execution profiles show that this function is called the most
+ * often of all non-spontaneous functions. So it had better be
+ * efficient. */
+void
+dlinkDelete(dlink_node *m, dlink_list *list)
+{
+ /* Assumption: If m->next == NULL, then list->tail == m
+ * and: If m->prev == NULL, then list->head == m
+ */
+ if (m->next)
+ m->next->prev = m->prev;
+ else
+ {
+ assert(list->tail == m);
+ list->tail = m->prev;
+ }
+
+ if (m->prev)
+ m->prev->next = m->next;
+ else
+ {
+ assert(list->head == m);
+ list->head = m->next;
+ }
+
+ /* Set this to NULL does matter */
+ m->next = m->prev = NULL;
+ list->length--;
+}
+
+/*
+ * dlinkFind
+ * inputs - list to search
+ * - data
+ * output - pointer to link or NULL if not found
+ * side effects - Look for ptr in the linked listed pointed to by link.
+ */
+dlink_node *
+dlinkFind(dlink_list *list, void *data)
+{
+ dlink_node *ptr;
+
+ DLINK_FOREACH(ptr, list->head)
+ if (ptr->data == data)
+ return ptr;
+
+ return NULL;
+}
+
+void
+dlinkMoveList(dlink_list *from, dlink_list *to)
+{
+ /* There are three cases */
+ /* case one, nothing in from list */
+ if (from->head == NULL)
+ return;
+
+ /* case two, nothing in to list */
+ /* actually if to->head is NULL and to->tail isn't, thats a bug */
+ if (to->head == NULL)
+ {
+ to->head = from->head;
+ to->tail = from->tail;
+ from->head = from->tail = NULL;
+ to->length = from->length;
+ from->length = 0;
+ return;
+ }
+
+ /* third case play with the links */
+ from->tail->next = to->head;
+ from->head->prev = to->head->prev;
+ to->head->prev = from->tail;
+ to->head = from->head;
+ from->head = from->tail = NULL;
+ to->length += from->length;
+ from->length = 0;
+ /* I think I got that right */
+}
+
+void
+dlink_move_node(dlink_node *m, dlink_list *list_del, dlink_list *list_add)
+{
+ /* Assumption: If m->next == NULL, then list_del->tail == m
+ * and: If m->prev == NULL, then list_del->head == m
+ */
+ if (m->next)
+ m->next->prev = m->prev;
+ else
+ {
+ assert(list->tail == m);
+ list_del->tail = m->prev;
+ }
+
+ if (m->prev)
+ m->prev->next = m->next;
+ else
+ {
+ assert(list->head == m);
+ list_del->head = m->next;
+ }
+
+ /* Set this to NULL does matter */
+ m->prev = NULL;
+ m->next = list_add->head;
+
+ /* Assumption: If list_add->tail != NULL, list_add->head != NULL */
+ if (list_add->head != NULL)
+ list_add->head->prev = m;
+ else if (list_add->tail == NULL)
+ list_add->tail = m;
+
+ list_add->head = m;
+ list_add->length++;
+ list_del->length--;
+}
+
+dlink_node *
+dlinkFindDelete(dlink_list *list, void *data)
+{
+ dlink_node *m;
+
+ DLINK_FOREACH(m, list->head)
+ {
+ if (m->data == data)
+ {
+ if (m->next)
+ m->next->prev = m->prev;
+ else
+ {
+ assert(list->tail == m);
+ list->tail = m->prev;
+ }
+ if (m->prev)
+ m->prev->next = m->next;
+ else
+ {
+ assert(list->head == m);
+ list->head = m->next;
+ }
+ /* Set this to NULL does matter */
+ m->next = m->prev = NULL;
+ list->length--;
+
+ return m;
+ }
+ }
+
+ return NULL;
+}
+
+