Haka
list2.h
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2  * License, v. 2.0. If a copy of the MPL was not distributed with this
3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4 
5 #ifndef HAKA_CONTAINER_LIST2_H
6 #define HAKA_CONTAINER_LIST2_H
7 
8 #include <haka/compiler.h>
9 #include <haka/types.h>
10 #include <stddef.h>
11 #include <assert.h>
12 
13 
14 struct list2_elem {
15  struct list2_elem *prev;
16  struct list2_elem *next;
17 #ifdef HAKA_DEBUG
18  bool is_end:1;
19  bool is_elem:1;
20 #endif
21 };
22 
23 struct list2 {
24  struct list2_elem head;
25 };
26 
27 #define LIST2_INIT { LIST2_ELEM_INIT }
28 
29 #define LIST2_ELEM_INIT { NULL, NULL }
30 
31 INLINE void list2_elem_init(struct list2_elem *elem)
32 {
33  elem->next = elem->prev = NULL;
34 #ifdef HAKA_DEBUG
35  elem->is_end = false;
36  elem->is_elem = true;
37 #endif
38 }
39 
40 INLINE bool list2_elem_check(struct list2_elem *elem) { return elem->next && elem->prev; }
41 
42 typedef struct list2_elem *list2_iter;
43 
44 INLINE list2_iter list2_begin(const struct list2 *list) { return list->head.next; }
45 INLINE list2_iter list2_end(const struct list2 *list) { return (list2_iter)&list->head; }
46 INLINE list2_iter list2_next(const list2_iter iter) { return iter->next; }
47 INLINE list2_iter list2_prev(const list2_iter iter) { return iter->prev; }
48 
49 void list2_init(struct list2 *list);
50 list2_iter list2_insert(list2_iter iter, struct list2_elem *elem);
51 list2_iter list2_insert_list(list2_iter iter, list2_iter begin, list2_iter end);
52 list2_iter list2_erase(list2_iter list);
53 INLINE bool list2_empty(const struct list2 *list) { return list2_begin(list) == list2_end(list); }
54 void list2_swap(struct list2 *a, struct list2 *b);
55 
56 INLINE void *_list2_getuserptr(struct list2_elem *l, size_t offset)
57 {
58 #ifdef HAKA_DEBUG
59  assert(l->is_elem);
60 #endif
61  return ((l) ? (void *)((char *)(l)-(offset)) : NULL);
62 }
63 
64 #define list2_get(iter, type, list) ((type*)_list2_getuserptr(iter, offsetof(type, list)))
65 #define list2_first(l, type, list) ((type*)(list2_empty((l)) ? NULL : _list2_getuserptr(list2_begin(l), offsetof(type, list))))
66 #define list2_last(l, type, list) ((type*)(list2_empty((l)) ? NULL : _list2_getuserptr(list2_prev(list2_end(l)), offsetof(type, list))))
67 
68 #endif /* HAKA_CONTAINER_LIST2_H */