2 * Copyright (C) 2024 Mikulas Patocka
4 * This file is part of Ajla.
6 * Ajla is free software: you can redistribute it and/or modify it under the
7 * terms of the GNU General Public License as published by the Free Software
8 * Foundation, either version 3 of the License, or (at your option) any later
11 * Ajla is distributed in the hope that it will be useful, but WITHOUT ANY
12 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
13 * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along with
16 * Ajla. If not, see <https://www.gnu.org/licenses/>.
23 struct list
*next
, *prev
;
27 static inline void list_verify(const struct list
*head
, const char *function
, const char *position
)
29 if (unlikely(head
->next
->prev
!= head
) ||
30 unlikely(head
->prev
->next
!= head
))
31 internal(position
, "list corrupted in %s: head %p, head->next %p, head->next->prev %p, head->prev %p, head->prev->next %p", function
, (const void *)head
, (const void *)head
->next
, (const void *)head
->next
->prev
, (const void *)head
->prev
, (const void *)head
->prev
->next
);
34 #define list_verify(head, position, function) ((void)0)
37 #define list_is_empty(entry) list_is_empty_(entry, file_line)
39 #define list_for_each(var, list) \
40 for (list_verify(list, "list_for_each 1", file_line), \
41 (var) = (list)->next, \
42 list_verify(var, "list_for_each 2", file_line); \
44 (var) = (var)->next, \
45 list_verify(var, "list_for_each 3", file_line))
47 #define list_for_each_back(var, list) \
48 for (list_verify(list, "list_for_each 1", file_line), \
49 (var) = (list)->prev, \
50 list_verify(var, "list_for_each_back 3", file_line); \
52 (var) = (var)->prev, \
53 list_verify(var, "list_for_each_back 3", file_line))
55 static inline void list_init(struct list
*head
)
57 head
->next
= head
->prev
= head
;
60 static inline void list_init_add(struct list
*head
, struct list
*entry
)
62 head
->next
= head
->prev
= entry
;
63 entry
->next
= entry
->prev
= head
;
66 static inline void list_add_(struct list
*head
, struct list
*entry
, const char attr_unused
*position
)
71 list_for_each(l
, head
) {
72 if (unlikely(l
== entry
))
73 internal(position
, "list_add: adding entry %p twice", entry
);
78 /*list_verify(head, "list_add 1", position);
79 list_verify(head->next, "list_add 2", position);*/
81 entry
->next
= head
->next
;
82 head
->next
->prev
= entry
;
86 #define list_add(head, entry) list_add_(head, entry, file_line)
88 static inline void list_del_(struct list
*entry
, const char attr_unused
*position
)
90 list_verify(entry
, "list_del", position
);
91 entry
->prev
->next
= entry
->next
;
92 entry
->next
->prev
= entry
->prev
;
94 entry
->next
= cast_cpp(struct list
*, BAD_POINTER_1
);
95 entry
->prev
= cast_cpp(struct list
*, BAD_POINTER_2
);
99 #define list_del(entry) list_del_(entry, file_line)
101 static inline bool list_is_empty_(struct list
*head
, const char attr_unused
*position
)
103 list_verify(head
, "list_is_empty", position
);
104 return head
->next
== head
;
107 static inline void list_take_(struct list
*dst
, struct list
*src
, const char attr_unused
*position
)
109 if (list_is_empty_(src
, position
)) {
113 dst
->next
->prev
= dst
;
114 dst
->prev
->next
= dst
;
119 #define list_take(dst, src) list_take_(dst, src, file_line)
122 static inline void list_join_(struct list
*dst
, struct list
*src
, const char attr_unused
*position
)
124 list_verify(dst
, "list_join dst", position
);
125 if (!list_is_empty_(src
, position
)) {
126 src
->next
->prev
= dst
;
127 src
->prev
->next
= dst
->next
;
128 dst
->next
->prev
= src
->prev
;
129 dst
->next
= src
->next
;
132 #define list_join(dst, src) list_join_(dst, src, file_line)