plist.c 5.85 KB
Newer Older
1
/*
Michael Beck's avatar
Michael Beck committed
2
 * Copyright (C) 1995-2008 University of Karlsruhe.  All right reserved.
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
 *
 * This file is part of libFirm.
 *
 * This file may be distributed and/or modified under the terms of the
 * GNU General Public License version 2 as published by the Free Software
 * Foundation and appearing in the file LICENSE.GPL included in the
 * packaging of this file.
 *
 * Licensees holding valid libFirm Professional Edition licenses may use
 * this file in accordance with the libFirm Commercial License.
 * Agreement provided with the Software.
 *
 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE.
 */

20
/**
Matthias Braun's avatar
Matthias Braun committed
21
22
23
24
25
26
27
28
29
 * @file
 * @brief Simple, non circular, double linked pointer list.
 * @note  Created because the properties of the standard circular list were not
 *        very well suited for the interference graph implementation.
 *        This list uses an obstack and a free-list to efficiently manage its
 *        elements.
 * @author  Kimon Hoffmann
 * @date    14.07.2005
 * @version $Id$
30
31
32
33
34
35
36
37
38
39
 */
#include <stdlib.h>

#include "plist.h"

/**
 * Helper macro that returns a new uninitialized list element by either
 * fetching one from the free-list or allocating a new one on the lists
 * obstack.
 * @param list the list for which to allocate the element.
Michael Beck's avatar
Michael Beck committed
40
 * @return the newly allocated, uninitialized element.
41
 */
42
43
static plist_element_t *allocate_element(plist_t* list)
{
44
	plist_element_t *new_element;
Christian Würdig's avatar
Christian Würdig committed
45
46

	if (list->first_free_element != NULL) {
47
48
49
		new_element              = list->first_free_element;
		list->first_free_element = new_element->next;
		new_element->next        = NULL;
Christian Würdig's avatar
Christian Würdig committed
50
51
	}
	else {
52
		new_element = OALLOC(list->obst, plist_element_t);
53
	}
Christian Würdig's avatar
Christian Würdig committed
54

55
	return new_element;
56
57
}

58
59
plist_t *plist_new(void)
{
Michael Beck's avatar
Michael Beck committed
60
	plist_t *list = xmalloc(sizeof(*list) + sizeof(*list->obst));
61

Michael Beck's avatar
Michael Beck committed
62
	list->obst               = (struct obstack *)&list[1];
63
	list->foreign_obstack    = 0;
Christian Würdig's avatar
Christian Würdig committed
64
65
66
67
68
	list->first_element      = NULL;
	list->last_element       = NULL;
	list->first_free_element = NULL;
	list->element_count      = 0;

Michael Beck's avatar
Michael Beck committed
69
	obstack_init(list->obst);
70
71
72
	return list;
}

73
74
plist_t *plist_obstack_new(struct obstack *obst)
{
75
	plist_t *list = OALLOC(obst, plist_t);
Christian Würdig's avatar
Christian Würdig committed
76

77
78
	list->obst               = obst;
	list->foreign_obstack    = 1;
Christian Würdig's avatar
Christian Würdig committed
79
80
81
82
	list->first_element      = NULL;
	list->last_element       = NULL;
	list->first_free_element = NULL;
	list->element_count      = 0;
83
84
85
86

	return list;
}

87
88
void plist_free(plist_t *list)
{
89
90
91
92
93
94
95
96
97
	list->first_element      = NULL;
	list->last_element       = NULL;
	list->first_free_element = NULL;
	list->element_count      = 0;

	if (! list->foreign_obstack) {
		obstack_free(list->obst, NULL);
		xfree(list);
	}
98
99
}

100
101
void plist_insert_back(plist_t *list, void *value)
{
Christian Würdig's avatar
Christian Würdig committed
102
103
104
105
	if (list->last_element != NULL) {
		plist_insert_after(list, list->last_element, value);
	}
	else {
Michael Beck's avatar
Michael Beck committed
106
		plist_element_t *newElement = allocate_element(list);
Christian Würdig's avatar
Christian Würdig committed
107
108
109
110
111
112

		newElement->data    = value;
		newElement->prev    = NULL;
		newElement->next    = NULL;
		list->first_element = list->last_element = newElement;
		list->element_count = 1;
113
114
115
	}
}

116
117
void plist_insert_front(plist_t *list, void *value)
{
Christian Würdig's avatar
Christian Würdig committed
118
119
120
121
	if (list->first_element != NULL) {
		plist_insert_before(list, list->first_element, value);
	}
	else {
Michael Beck's avatar
Michael Beck committed
122
		plist_element_t *newElement = allocate_element(list);
Christian Würdig's avatar
Christian Würdig committed
123
124
125
126
127
128

		newElement->data    = value;
		newElement->prev    = NULL;
		newElement->next    = NULL;
		list->first_element = list->last_element = newElement;
		list->element_count = 1;
129
130
131
	}
}

132
133
void plist_insert_before(plist_t *list, plist_element_t *element, void *value)
{
Michael Beck's avatar
Michael Beck committed
134
135
	plist_element_t *prevElement;
	plist_element_t *newElement = allocate_element(list);
Michael Beck's avatar
Michael Beck committed
136

137
138
	newElement->data = value;
	newElement->next = element;
Christian Würdig's avatar
Christian Würdig committed
139
	prevElement      = element->prev;
140
	newElement->prev = prevElement;
Christian Würdig's avatar
Christian Würdig committed
141

142
143
144
	if (prevElement != NULL) {
		prevElement->next = newElement;
	}
Christian Würdig's avatar
Christian Würdig committed
145
146
147
148
149
150
	else {
		list->first_element = newElement;
	}

 	element->prev = newElement;
	++list->element_count;
151
152
}

153
154
void plist_insert_after(plist_t* list, plist_element_t* element, void* value)
{
Michael Beck's avatar
Michael Beck committed
155
156
	plist_element_t *nextElement;
	plist_element_t *newElement = allocate_element(list);
Michael Beck's avatar
Michael Beck committed
157

158
159
	newElement->data = value;
	newElement->prev = element;
Christian Würdig's avatar
Christian Würdig committed
160
	nextElement      = element->next;
161
	newElement->next = nextElement;
Christian Würdig's avatar
Christian Würdig committed
162

163
164
165
	if (nextElement != NULL) {
		nextElement->prev = newElement;
	}
Christian Würdig's avatar
Christian Würdig committed
166
167
168
169
	else {
		list->last_element = newElement;
	}

170
	element->next = newElement;
Christian Würdig's avatar
Christian Würdig committed
171
	++list->element_count;
172
173
}

174
175
int plist_has_value(plist_t *list, void *value)
{
176
177
178
179
180
181
182
183
184
185
	plist_element_t *iter;

	for (iter = plist_first(list); iter; iter = plist_element_get_next(iter)) {
		if (plist_element_get_value(iter) == value)
			return 1;
	}

	return 0;
}

186
187
plist_element_t *plist_find_value(plist_t *list, void *value)
{
188
189
190
191
192
193
194
195
196
197
	plist_element_t *iter;

	for (iter = plist_first(list); iter; iter = plist_element_get_next(iter)) {
		if (plist_element_get_value(iter) == value)
			return iter;
	}

	return NULL;
}

198
199
void plist_erase(plist_t *list, plist_element_t *element)
{
200
201
	plist_element_t *next_element = element->next;
	plist_element_t *prev_element = element->prev;
Christian Würdig's avatar
Christian Würdig committed
202

203
204
	if (next_element != NULL) {
		next_element->prev = prev_element;
205
	}
Christian Würdig's avatar
Christian Würdig committed
206
	else {
207
		list->last_element = prev_element;
Christian Würdig's avatar
Christian Würdig committed
208
209
	}

210
211
	if (prev_element != NULL) {
		prev_element->next = next_element;
212
	}
Christian Würdig's avatar
Christian Würdig committed
213
	else {
214
		list->first_element = next_element;
Christian Würdig's avatar
Christian Würdig committed
215
216
217
218
	}

	--list->element_count;

219
	/* Clean the element and prepend it to the free list */
Christian Würdig's avatar
Christian Würdig committed
220
221
222
	element->prev            = NULL; /* The allocation code expects prev to be NULL */
	element->next            = list->first_free_element;
	list->first_free_element = element;
223
224
}

225
226
void plist_clear(plist_t *list)
{
227
	plist_element_t *curr_element = list->first_element;
Christian Würdig's avatar
Christian Würdig committed
228

229
230
231
	while (curr_element != NULL) {
		curr_element->prev = NULL;
		curr_element       = curr_element->next;
232
	}
Christian Würdig's avatar
Christian Würdig committed
233

234
	curr_element = list->last_element;
Christian Würdig's avatar
Christian Würdig committed
235

236
237
	if (curr_element != NULL) {
		curr_element->next = list->first_free_element;
238
	}
Christian Würdig's avatar
Christian Würdig committed
239
240
241
242
243

	list->first_free_element = list->first_element;
	list->first_element      = 0;
	list->last_element       = 0;
	list->element_count      = 0;
244
}