/*------------------------------------------------------------------------- * * ilist.c * support for integrated/inline doubly- and singly- linked lists * * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION * src/backend/lib/ilist.c * * NOTES * This file only contains functions that are too big to be considered * for inlining. See ilist.h for most of the goodies. * *------------------------------------------------------------------------- */ #include "postgres.h" #include "lib/ilist.h" /* * Delete 'node' from list. * * It is not allowed to delete a 'node' which is not in the list 'head' * * Caution: this is O(n); consider using slist_delete_current() instead. */ void slist_delete(slist_head *head, const slist_node *node) { slist_node *last = &head->head; slist_node *cur; bool found PG_USED_FOR_ASSERTS_ONLY = false; while ((cur = last->next) != NULL) { if (cur == node) { last->next = cur->next; #ifdef USE_ASSERT_CHECKING found = true; #endif break; } last = cur; } Assert(found); slist_check(head); } #ifdef ILIST_DEBUG /* * dlist_member_check * Validate that 'node' is a member of 'head' */ void dlist_member_check(const dlist_head *head, const dlist_node *node) { const dlist_node *cur; /* iteration open-coded to due to the use of const */ for (cur = head->head.next; cur != &head->head; cur = cur->next) { if (cur == node) return; } elog(ERROR, "double linked list member check failure"); } /* * Verify integrity of a doubly linked list */ void dlist_check(const dlist_head *head) { dlist_node *cur; if (head == NULL) elog(ERROR, "doubly linked list head address is NULL"); if (head->head.next == NULL && head->head.prev == NULL) return; /* OK, initialized as zeroes */ /* iterate in forward direction */ for (cur = head->head.next; cur != &head->head; cur = cur->next) { if (cur == NULL || cur->next == NULL || cur->prev == NULL || cur->prev->next != cur || cur->next->prev != cur) elog(ERROR, "doubly linked list is corrupted"); } /* iterate in backward direction */ for (cur = head->head.prev; cur != &head->head; cur = cur->prev) { if (cur == NULL || cur->next == NULL || cur->prev == NULL || cur->prev->next != cur || cur->next->prev != cur) elog(ERROR, "doubly linked list is corrupted"); } } /* * Verify integrity of a singly linked list */ void slist_check(const slist_head *head) { slist_node *cur; if (head == NULL) elog(ERROR, "singly linked list head address is NULL"); /* * there isn't much we can test in a singly linked list except that it * actually ends sometime, i.e. hasn't introduced a cycle or similar */ for (cur = head->head.next; cur != NULL; cur = cur->next) ; } #endif /* ILIST_DEBUG */