tools/llvm: Do not build with symbols
[minix3.git] / external / bsd / atf / dist / atf-c / detail / list.c
blob0d005ad051816508e76f662927596c1b585a3432
1 /*
2 * Automated Testing Framework (atf)
4 * Copyright (c) 2008 The NetBSD Foundation, Inc.
5 * All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND
17 * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
18 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY
21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
23 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 #include <stdlib.h>
31 #include <string.h>
33 #include "atf-c/error.h"
34 #include "atf-c/utils.h"
36 #include "list.h"
37 #include "sanity.h"
39 /* ---------------------------------------------------------------------
40 * Auxiliary functions.
41 * --------------------------------------------------------------------- */
43 struct list_entry {
44 struct list_entry *m_prev;
45 struct list_entry *m_next;
46 void *m_object;
47 bool m_managed;
50 static
51 atf_list_citer_t
52 entry_to_citer(const atf_list_t *l, const struct list_entry *le)
54 atf_list_citer_t iter;
55 iter.m_list = l;
56 iter.m_entry = le;
57 return iter;
60 static
61 atf_list_iter_t
62 entry_to_iter(atf_list_t *l, struct list_entry *le)
64 atf_list_iter_t iter;
65 iter.m_list = l;
66 iter.m_entry = le;
67 return iter;
70 static
71 struct list_entry *
72 new_entry(void *object, bool managed)
74 struct list_entry *le;
76 le = (struct list_entry *)malloc(sizeof(*le));
77 if (le != NULL) {
78 le->m_prev = le->m_next = NULL;
79 le->m_object = object;
80 le->m_managed = managed;
81 } else
82 free(object);
84 return le;
87 static
88 void
89 delete_entry(struct list_entry *le)
91 if (le->m_managed)
92 free(le->m_object);
94 free(le);
97 static
98 struct list_entry *
99 new_entry_and_link(void *object, bool managed, struct list_entry *prev,
100 struct list_entry *next)
102 struct list_entry *le;
104 le = new_entry(object, managed);
105 if (le != NULL) {
106 le->m_prev = prev;
107 le->m_next = next;
109 prev->m_next = le;
110 next->m_prev = le;
113 return le;
116 /* ---------------------------------------------------------------------
117 * The "atf_list_citer" type.
118 * --------------------------------------------------------------------- */
121 * Getters.
124 const void *
125 atf_list_citer_data(const atf_list_citer_t citer)
127 const struct list_entry *le = citer.m_entry;
128 PRE(le != NULL);
129 return le->m_object;
132 atf_list_citer_t
133 atf_list_citer_next(const atf_list_citer_t citer)
135 const struct list_entry *le = citer.m_entry;
136 atf_list_citer_t newciter;
138 PRE(le != NULL);
140 newciter = citer;
141 newciter.m_entry = le->m_next;
143 return newciter;
146 bool
147 atf_equal_list_citer_list_citer(const atf_list_citer_t i1,
148 const atf_list_citer_t i2)
150 return i1.m_list == i2.m_list && i1.m_entry == i2.m_entry;
153 /* ---------------------------------------------------------------------
154 * The "atf_list_iter" type.
155 * --------------------------------------------------------------------- */
158 * Getters.
161 void *
162 atf_list_iter_data(const atf_list_iter_t iter)
164 const struct list_entry *le = iter.m_entry;
165 PRE(le != NULL);
166 return le->m_object;
169 atf_list_iter_t
170 atf_list_iter_next(const atf_list_iter_t iter)
172 const struct list_entry *le = iter.m_entry;
173 atf_list_iter_t newiter;
175 PRE(le != NULL);
177 newiter = iter;
178 newiter.m_entry = le->m_next;
180 return newiter;
183 bool
184 atf_equal_list_iter_list_iter(const atf_list_iter_t i1,
185 const atf_list_iter_t i2)
187 return i1.m_list == i2.m_list && i1.m_entry == i2.m_entry;
190 /* ---------------------------------------------------------------------
191 * The "atf_list" type.
192 * --------------------------------------------------------------------- */
195 * Constructors and destructors.
198 atf_error_t
199 atf_list_init(atf_list_t *l)
201 struct list_entry *lebeg, *leend;
203 lebeg = new_entry(NULL, false);
204 if (lebeg == NULL) {
205 return atf_no_memory_error();
208 leend = new_entry(NULL, false);
209 if (leend == NULL) {
210 free(lebeg);
211 return atf_no_memory_error();
214 lebeg->m_next = leend;
215 lebeg->m_prev = NULL;
217 leend->m_next = NULL;
218 leend->m_prev = lebeg;
220 l->m_size = 0;
221 l->m_begin = lebeg;
222 l->m_end = leend;
224 return atf_no_error();
227 void
228 atf_list_fini(atf_list_t *l)
230 struct list_entry *le;
231 size_t freed;
233 le = (struct list_entry *)l->m_begin;
234 freed = 0;
235 while (le != NULL) {
236 struct list_entry *lenext;
238 lenext = le->m_next;
239 delete_entry(le);
240 le = lenext;
242 freed++;
244 INV(freed == l->m_size + 2);
248 * Getters.
251 atf_list_iter_t
252 atf_list_begin(atf_list_t *l)
254 struct list_entry *le = l->m_begin;
255 return entry_to_iter(l, le->m_next);
258 atf_list_citer_t
259 atf_list_begin_c(const atf_list_t *l)
261 const struct list_entry *le = l->m_begin;
262 return entry_to_citer(l, le->m_next);
265 atf_list_iter_t
266 atf_list_end(atf_list_t *l)
268 return entry_to_iter(l, l->m_end);
271 atf_list_citer_t
272 atf_list_end_c(const atf_list_t *l)
274 return entry_to_citer(l, l->m_end);
277 void *
278 atf_list_index(atf_list_t *list, const size_t idx)
280 atf_list_iter_t iter;
282 PRE(idx < atf_list_size(list));
284 iter = atf_list_begin(list);
286 size_t pos = 0;
287 while (pos < idx &&
288 !atf_equal_list_iter_list_iter((iter), atf_list_end(list))) {
289 iter = atf_list_iter_next(iter);
290 pos++;
293 return atf_list_iter_data(iter);
296 const void *
297 atf_list_index_c(const atf_list_t *list, const size_t idx)
299 atf_list_citer_t iter;
301 PRE(idx < atf_list_size(list));
303 iter = atf_list_begin_c(list);
305 size_t pos = 0;
306 while (pos < idx &&
307 !atf_equal_list_citer_list_citer((iter),
308 atf_list_end_c(list))) {
309 iter = atf_list_citer_next(iter);
310 pos++;
313 return atf_list_citer_data(iter);
316 size_t
317 atf_list_size(const atf_list_t *l)
319 return l->m_size;
322 char **
323 atf_list_to_charpp(const atf_list_t *l)
325 char **array;
326 atf_list_citer_t iter;
327 size_t i;
329 array = malloc(sizeof(char *) * (atf_list_size(l) + 1));
330 if (array == NULL)
331 goto out;
333 i = 0;
334 atf_list_for_each_c(iter, l) {
335 array[i] = strdup((const char *)atf_list_citer_data(iter));
336 if (array[i] == NULL) {
337 atf_utils_free_charpp(array);
338 array = NULL;
339 goto out;
342 i++;
344 array[i] = NULL;
346 out:
347 return array;
351 * Modifiers.
354 atf_error_t
355 atf_list_append(atf_list_t *l, void *data, bool managed)
357 struct list_entry *le, *next, *prev;
358 atf_error_t err;
360 next = (struct list_entry *)l->m_end;
361 prev = next->m_prev;
362 le = new_entry_and_link(data, managed, prev, next);
363 if (le == NULL)
364 err = atf_no_memory_error();
365 else {
366 l->m_size++;
367 err = atf_no_error();
370 return err;
373 void
374 atf_list_append_list(atf_list_t *l, atf_list_t *src)
376 struct list_entry *e1, *e2, *ghost1, *ghost2;
378 ghost1 = (struct list_entry *)l->m_end;
379 ghost2 = (struct list_entry *)src->m_begin;
381 e1 = ghost1->m_prev;
382 e2 = ghost2->m_next;
384 delete_entry(ghost1);
385 delete_entry(ghost2);
387 e1->m_next = e2;
388 e2->m_prev = e1;
390 l->m_end = src->m_end;
391 l->m_size += src->m_size;