GFXprim
2D bitmap graphics library with emphasis on speed and correctness
Loading...
Searching...
No Matches
gp_list.h
Go to the documentation of this file.
1//SPDX-License-Identifier: LGPL-2.0-or-later
2
3/*
4
5 Copyright (C) 2007-2021 Cyril Hrubis <metan@ucw.cz>
6
7 */
8
14#ifndef GP_LIST_H
15#define GP_LIST_H
16
17#include <core/gp_common.h>
18
19typedef struct gp_list_head {
20 struct gp_list_head *next;
21} gp_list_head;
22
23typedef struct gp_dlist_head {
24 struct gp_dlist_head *next;
25 struct gp_dlist_head *prev;
26} gp_dlist_head;
27
28typedef struct gp_list {
29 gp_list_head *head;
30 gp_list_head *tail;
31 size_t cnt;
32} gp_list;
33
34typedef struct gp_dlist {
35 gp_dlist_head *head;
36 gp_dlist_head *tail;
37 size_t cnt;
38} gp_dlist;
39
40#define GP_LIST_ENTRY(ptr, structure, member) \
41 GP_CONTAINER_OF(ptr, structure, member)
42
43#define GP_LIST_FOREACH(list, entry) \
44 for (entry = (list)->head; entry; entry = entry->next)
45
46#define GP_DLIST_REV_FOREACH(list, entry) \
47 for (entry = (list)->tail; entry; entry = entry->prev)
48
55static inline void gp_list_push_head(gp_list *list, gp_list_head *entry)
56{
57 if (!list->head)
58 list->tail = entry;
59
60 entry->next = list->head;
61 list->head = entry;
62
63 list->cnt++;
64}
65
72static inline void gp_dlist_push_head(gp_dlist *list, gp_dlist_head *entry)
73{
74 gp_list_push_head((gp_list *)list, (gp_list_head*)entry);
75
76 entry->prev = NULL;
77 if (entry->next)
78 entry->next->prev = entry;
79}
80
81/*
82 * Internal do not touch.
83 */
84static inline void gp_list_push_tail_(gp_list *list, gp_list_head *entry)
85{
86 entry->next = NULL;
87
88 if (!list->head)
89 list->head = entry;
90 else
91 list->tail->next = entry;
92
93 list->cnt++;
94}
95
102static inline void gp_list_push_tail(gp_list *list, gp_list_head *entry)
103{
104 gp_list_push_tail_(list, entry);
105
106 list->tail = entry;
107}
108
115static inline void gp_dlist_push_tail(gp_dlist *list, gp_dlist_head *entry)
116{
117 gp_list_push_tail_((gp_list *)list, (gp_list_head*)entry);
118
119 entry->prev = list->tail;
120 list->tail = entry;
121}
122
130static inline void gp_dlist_push_after(gp_dlist *list, gp_dlist_head *after, gp_dlist_head *entry)
131{
132 entry->prev = after;
133 entry->next = after->next;
134
135 if (after->next)
136 after->next->prev = entry;
137 else
138 list->tail = entry;
139
140 after->next = entry;
141
142 list->cnt++;
143}
144
152static inline void gp_dlist_push_before(gp_dlist *list, gp_dlist_head *before, gp_dlist_head *entry)
153{
154 entry->next = before;
155 entry->prev = before->prev;
156
157 if (before->prev)
158 before->prev->next = entry;
159 else
160 list->head = entry;
161
162 before->prev = entry;
163
164 list->cnt++;
165}
166
175static inline gp_list_head *gp_list_pop_head(gp_list *list)
176{
177 gp_list_head *ret = list->head;
178
179 if (!ret)
180 return NULL;
181
182 if (!ret->next)
183 list->tail = NULL;
184
185 list->head = list->head->next;
186 list->cnt--;
187
188 return ret;
189}
190
199static inline gp_dlist_head *gp_dlist_pop_head(gp_dlist *list)
200{
201 gp_dlist_head *ret;
202
203 ret = (gp_dlist_head*)gp_list_pop_head((gp_list*)list);
204
205 if (ret && ret->next)
206 ret->next->prev = NULL;
207
208 return ret;
209}
210
219static inline gp_dlist_head *gp_dlist_pop_tail(gp_dlist *list)
220{
221 gp_dlist_head *ret = list->tail;
222
223 if (!ret)
224 return NULL;
225
226 list->tail = ret->prev;
227
228 if (!ret->prev)
229 list->head = NULL;
230 else
231 ret->prev->next = NULL;
232
233 list->cnt--;
234
235 return ret;
236}
237
246static inline void gp_dlist_rem(gp_dlist *list, gp_dlist_head *entry)
247{
248 if (entry->prev)
249 entry->prev->next = entry->next;
250 else
251 list->head = entry->next;
252
253 if (entry->next)
254 entry->next->prev = entry->prev;
255 else
256 list->tail = entry->prev;
257
258 list->cnt--;
259}
260
261/*
262 * Internal function, do not call.
263 */
264static inline gp_list_head *gp_list_merge_sort(gp_list_head *head,
265 int (*cmp)(const void *, const void *))
266{
267 gp_list_head *middle, *tmp, *ret;
268
269 if (!head || !head->next)
270 return head;
271
272 for (middle = tmp = head; tmp; tmp = tmp->next) {
273 ret = middle;
274 middle = middle->next;
275 if (tmp->next)
276 tmp = tmp->next;
277 }
278
279 ret->next = NULL;
280 head = gp_list_merge_sort(head, cmp);
281 middle = gp_list_merge_sort(middle, cmp);
282
283 if (cmp(head, middle)) {
284 ret = tmp = head;
285 head = head->next;
286 } else {
287 ret = tmp = middle;
288 middle = middle->next;
289 }
290
291 while (head || middle) {
292 while (head && (!middle || cmp(middle, head) <= 0)) {
293 tmp->next = head;
294 tmp = head;
295 head = head->next;
296 }
297
298 while (middle && (!head || cmp(head, middle) <= 0)) {
299 tmp->next = middle;
300 tmp = middle;
301 middle = middle->next;
302 }
303 }
304
305 tmp->next = NULL;
306
307 return ret;
308}
309
336static inline void gp_list_sort(gp_list *list,
337 int (*cmp)(const void *, const void *))
338{
339 gp_list_head *tail;
340
341 if (!list->head)
342 return;
343
344 list->head = gp_list_merge_sort(list->head, cmp);
345
346 for (tail = list->head; tail->next; tail = tail->next);
347
348 list->tail = tail;
349}
350
359static inline void gp_dlist_sort(gp_dlist *list,
360 int (*cmp)(const void *, const void *))
361{
362 gp_dlist_head *i;
363
364 if (!list->head)
365 return;
366
367 list->head = (gp_dlist_head*)gp_list_merge_sort((gp_list_head*)list->head, cmp);
368
369 if (list->head)
370 list->head->prev = NULL;
371
372 for (i = list->head; i->next; i = i->next)
373 i->next->prev = i;
374
375 list->tail = i;
376}
377
378#endif /* GP_LIST_H */
Common macros.
static void gp_dlist_push_tail(gp_dlist *list, gp_dlist_head *entry)
Pushes into tail of double linked list.
Definition gp_list.h:115
static void gp_dlist_push_after(gp_dlist *list, gp_dlist_head *after, gp_dlist_head *entry)
Pushes an entry into a double linked list after an entry.
Definition gp_list.h:130
static gp_dlist_head * gp_dlist_pop_head(gp_dlist *list)
Pops from a head of a double linked list.
Definition gp_list.h:199
static void gp_dlist_push_before(gp_dlist *list, gp_dlist_head *before, gp_dlist_head *entry)
Pushes an entry into a double linked list before an entry.
Definition gp_list.h:152
static gp_list_head * gp_list_pop_head(gp_list *list)
Pops from a head of a linked list.
Definition gp_list.h:175
static void gp_list_push_tail(gp_list *list, gp_list_head *entry)
Pushes into tail of linked list.
Definition gp_list.h:102
static void gp_dlist_rem(gp_dlist *list, gp_dlist_head *entry)
Removes a entry from a double linked list.
Definition gp_list.h:246
static void gp_list_push_head(gp_list *list, gp_list_head *entry)
Pushes into head of linked list.
Definition gp_list.h:55
static void gp_dlist_push_head(gp_dlist *list, gp_dlist_head *entry)
Pushes into head of double linked list.
Definition gp_list.h:72
static gp_dlist_head * gp_dlist_pop_tail(gp_dlist *list)
Pops from a tail of a double linked list.
Definition gp_list.h:219
static void gp_dlist_sort(gp_dlist *list, int(*cmp)(const void *, const void *))
Sorts a double linked list given a compare function.
Definition gp_list.h:359
static void gp_list_sort(gp_list *list, int(*cmp)(const void *, const void *))
Sorts a linked list given a element comparsion function.
Definition gp_list.h:336