dllist.c 3.86 KB
Newer Older
1 2
/*-------------------------------------------------------------------------
 *
3
 * dllist.c
4 5
 *	  this is a simple doubly linked list implementation
 *	  the elements of the lists are void*
6
 *
7
 * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
Bruce Momjian's avatar
Add:  
Bruce Momjian committed
8
 * Portions Copyright (c) 1994, Regents of the University of California
9 10 11
 *
 *
 * IDENTIFICATION
Tom Lane's avatar
Tom Lane committed
12
 *	  $Header: /cvsroot/pgsql/src/backend/lib/dllist.c,v 1.22 2001/06/01 19:54:58 tgl Exp $
13 14 15 16
 *
 *-------------------------------------------------------------------------
 */

17
/* can be used in frontend or backend */
18
#ifdef FRONTEND
19 20
#include "postgres_fe.h"
/* No assert checks in frontend ... */
21
#define Assert(condition)
22 23
#else
#include "postgres.h"
24 25
#endif

26 27
#include "lib/dllist.h"

28

29
Dllist *
30
DLNewList(void)
31
{
32
	Dllist	   *l;
33

34
	l = (Dllist *) malloc(sizeof(Dllist));
Tom Lane's avatar
Tom Lane committed
35 36
	if (l == NULL)
		elog(ERROR, "Memory exhausted in DLNewList");
37 38
	l->dll_head = 0;
	l->dll_tail = 0;
39

40
	return l;
41 42
}

43 44 45 46 47 48 49 50 51
void
DLInitList(Dllist *list)
{
	list->dll_head = 0;
	list->dll_tail = 0;
}

/*
 * free up a list and all the nodes in it --- but *not* whatever the nodes
52 53
 * might point to!
 */
54
void
55
DLFreeList(Dllist *list)
56
{
57
	Dlelem	   *curr;
58

59
	while ((curr = DLRemHead(list)) != 0)
60
		free(curr);
61

62
	free(list);
63 64
}

65
Dlelem *
66
DLNewElem(void *val)
67
{
68
	Dlelem	   *e;
69

70
	e = (Dlelem *) malloc(sizeof(Dlelem));
Tom Lane's avatar
Tom Lane committed
71 72
	if (e == NULL)
		elog(ERROR, "Memory exhausted in DLNewElem");
73 74 75 76 77
	e->dle_next = 0;
	e->dle_prev = 0;
	e->dle_val = val;
	e->dle_list = 0;
	return e;
78 79 80
}

void
81
DLInitElem(Dlelem *e, void *val)
82
{
83 84 85 86
	e->dle_next = 0;
	e->dle_prev = 0;
	e->dle_val = val;
	e->dle_list = 0;
87 88
}

89 90
void
DLFreeElem(Dlelem *e)
91
{
92
	free(e);
93 94 95
}

void
96
DLRemove(Dlelem *e)
97
{
98
	Dllist	   *l = e->dle_list;
99

100 101
	if (e->dle_prev)
		e->dle_prev->dle_next = e->dle_next;
102
	else
103
	{
104
		/* must be the head element */
105 106 107
		Assert(e == l->dll_head);
		l->dll_head = e->dle_next;
	}
108 109
	if (e->dle_next)
		e->dle_next->dle_prev = e->dle_prev;
110
	else
111
	{
112
		/* must be the tail element */
113 114 115
		Assert(e == l->dll_tail);
		l->dll_tail = e->dle_prev;
	}
116

117 118 119
	e->dle_next = 0;
	e->dle_prev = 0;
	e->dle_list = 0;
120 121
}

122
void
123
DLAddHead(Dllist *l, Dlelem *e)
124
{
125 126 127 128
	e->dle_list = l;

	if (l->dll_head)
		l->dll_head->dle_prev = e;
129
	e->dle_next = l->dll_head;
130 131 132 133
	e->dle_prev = 0;
	l->dll_head = e;

	if (l->dll_tail == 0)		/* if this is first element added */
134
		l->dll_tail = e;
135 136 137
}

void
138
DLAddTail(Dllist *l, Dlelem *e)
139
{
140 141 142 143
	e->dle_list = l;

	if (l->dll_tail)
		l->dll_tail->dle_next = e;
144
	e->dle_prev = l->dll_tail;
145 146 147 148
	e->dle_next = 0;
	l->dll_tail = e;

	if (l->dll_head == 0)		/* if this is first element added */
149
		l->dll_head = e;
150 151
}

152
Dlelem *
153
DLRemHead(Dllist *l)
154
{
155
	/* remove and return the head */
156
	Dlelem	   *result = l->dll_head;
157

158 159
	if (result == 0)
		return result;
160

161 162
	if (result->dle_next)
		result->dle_next->dle_prev = 0;
163

164
	l->dll_head = result->dle_next;
165

166 167 168
	if (result == l->dll_tail)	/* if the head is also the tail */
		l->dll_tail = 0;

169 170 171
	result->dle_next = 0;
	result->dle_list = 0;

172
	return result;
173 174
}

175
Dlelem *
176
DLRemTail(Dllist *l)
177
{
178
	/* remove and return the tail */
179
	Dlelem	   *result = l->dll_tail;
180

181 182
	if (result == 0)
		return result;
183

184 185 186 187
	if (result->dle_prev)
		result->dle_prev->dle_next = 0;

	l->dll_tail = result->dle_prev;
188

189 190
	if (result == l->dll_head)	/* if the tail is also the head */
		l->dll_head = 0;
191

192 193 194
	result->dle_prev = 0;
	result->dle_list = 0;

195
	return result;
196
}
197 198 199 200 201 202 203 204 205 206 207 208 209 210 211

/* Same as DLRemove followed by DLAddHead, but faster */
void
DLMoveToFront(Dlelem *e)
{
	Dllist	   *l = e->dle_list;

	if (l->dll_head == e)
		return;					/* Fast path if already at front */

	Assert(e->dle_prev != 0);	/* since it's not the head */
	e->dle_prev->dle_next = e->dle_next;

	if (e->dle_next)
		e->dle_next->dle_prev = e->dle_prev;
212
	else
213
	{
214
		/* must be the tail element */
215 216 217 218 219 220 221 222 223 224
		Assert(e == l->dll_tail);
		l->dll_tail = e->dle_prev;
	}

	l->dll_head->dle_prev = e;
	e->dle_next = l->dll_head;
	e->dle_prev = 0;
	l->dll_head = e;
	/* We need not check dll_tail, since there must have been > 1 entry */
}