2012-10-16 22:36:30 +02:00
|
|
|
/*-------------------------------------------------------------------------
|
|
|
|
*
|
|
|
|
* ilist.c
|
|
|
|
* support for integrated/inline doubly- and singly- linked lists
|
|
|
|
*
|
2013-01-01 23:15:01 +01:00
|
|
|
* Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
|
2012-10-16 22:36:30 +02:00
|
|
|
* 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"
|
|
|
|
|
|
|
|
/* See ilist.h */
|
|
|
|
#define ILIST_INCLUDE_DEFINITIONS
|
|
|
|
|
|
|
|
#include "lib/ilist.h"
|
|
|
|
|
|
|
|
/*
|
2012-10-18 22:47:07 +02:00
|
|
|
* Delete 'node' from list.
|
2012-10-16 22:36:30 +02:00
|
|
|
*
|
2012-10-18 22:47:07 +02:00
|
|
|
* It is not allowed to delete a 'node' which is is not in the list 'head'
|
|
|
|
*
|
2013-07-24 23:41:55 +02:00
|
|
|
* Caution: this is O(n); consider using slist_delete_current() instead.
|
2012-10-16 22:36:30 +02:00
|
|
|
*/
|
|
|
|
void
|
|
|
|
slist_delete(slist_head *head, 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;
|
|
|
|
}
|
2012-10-18 22:47:07 +02:00
|
|
|
Assert(found);
|
2012-10-16 22:36:30 +02:00
|
|
|
|
|
|
|
slist_check(head);
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef ILIST_DEBUG
|
|
|
|
/*
|
|
|
|
* Verify integrity of a doubly linked list
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
dlist_check(dlist_head *head)
|
|
|
|
{
|
|
|
|
dlist_node *cur;
|
|
|
|
|
2012-10-18 22:47:07 +02:00
|
|
|
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 */
|
2012-10-16 22:36:30 +02:00
|
|
|
|
|
|
|
/* 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(slist_head *head)
|
|
|
|
{
|
|
|
|
slist_node *cur;
|
|
|
|
|
|
|
|
if (head == NULL)
|
2012-10-18 22:47:07 +02:00
|
|
|
elog(ERROR, "singly linked list head address is NULL");
|
2012-10-16 22:36:30 +02:00
|
|
|
|
|
|
|
/*
|
2012-10-18 22:47:07 +02:00
|
|
|
* there isn't much we can test in a singly linked list except that it
|
2012-10-16 22:36:30 +02:00
|
|
|
* 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 */
|