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
28
40
52
64
72#define GP_LIST_ENTRY(ptr, structure, member) \
73 GP_CONTAINER_OF(ptr, structure, member)
74
100#define GP_LIST_FOREACH(list, entry) \
101 for (entry = (list)->head; entry; entry = entry->next)
102
130#define GP_DLIST_REV_FOREACH(list, entry) \
131 for (entry = (list)->tail; entry; entry = entry->prev)
132
139static inline void gp_list_push_head(gp_list *list, gp_list_head *entry)
140{
141 if (!list->head)
142 list->tail = entry;
143
144 entry->next = list->head;
145 list->head = entry;
146
147 list->cnt++;
148}
149
156static inline void gp_dlist_push_head(gp_dlist *list, gp_dlist_head *entry)
157{
158 gp_list_push_head((gp_list *)list, (gp_list_head*)entry);
159
160 entry->prev = NULL;
161 if (entry->next)
162 entry->next->prev = entry;
163}
164
165/*
166 * Internal do not touch.
167 */
168static inline void gp_list_push_tail_(gp_list *list, gp_list_head *entry)
169{
170 entry->next = NULL;
171
172 if (!list->head)
173 list->head = entry;
174 else
175 list->tail->next = entry;
176
177 list->cnt++;
178}
179
186static inline void gp_list_push_tail(gp_list *list, gp_list_head *entry)
187{
188 gp_list_push_tail_(list, entry);
189
190 list->tail = entry;
191}
192
199static inline void gp_dlist_push_tail(gp_dlist *list, gp_dlist_head *entry)
200{
201 gp_list_push_tail_((gp_list *)list, (gp_list_head*)entry);
202
203 entry->prev = list->tail;
204 list->tail = entry;
205}
206
214static inline void gp_dlist_push_after(gp_dlist *list, gp_dlist_head *after, gp_dlist_head *entry)
215{
216 entry->prev = after;
217 entry->next = after->next;
218
219 if (after->next)
220 after->next->prev = entry;
221 else
222 list->tail = entry;
223
224 after->next = entry;
225
226 list->cnt++;
227}
228
236static inline void gp_dlist_push_before(gp_dlist *list, gp_dlist_head *before, gp_dlist_head *entry)
237{
238 entry->next = before;
239 entry->prev = before->prev;
240
241 if (before->prev)
242 before->prev->next = entry;
243 else
244 list->head = entry;
245
246 before->prev = entry;
247
248 list->cnt++;
249}
250
260{
261 gp_list_head *ret = list->head;
262
263 if (!ret)
264 return NULL;
265
266 if (!ret->next)
267 list->tail = NULL;
268
269 list->head = list->head->next;
270 list->cnt--;
271
272 return ret;
273}
274
284{
285 gp_dlist_head *ret;
286
287 ret = (gp_dlist_head*)gp_list_pop_head((gp_list*)list);
288
289 if (ret && ret->next)
290 ret->next->prev = NULL;
291
292 return ret;
293}
294
304{
305 gp_dlist_head *ret = list->tail;
306
307 if (!ret)
308 return NULL;
309
310 list->tail = ret->prev;
311
312 if (!ret->prev)
313 list->head = NULL;
314 else
315 ret->prev->next = NULL;
316
317 list->cnt--;
318
319 return ret;
320}
321
330static inline void gp_dlist_rem(gp_dlist *list, gp_dlist_head *entry)
331{
332 if (entry->prev)
333 entry->prev->next = entry->next;
334 else
335 list->head = entry->next;
336
337 if (entry->next)
338 entry->next->prev = entry->prev;
339 else
340 list->tail = entry->prev;
341
342 list->cnt--;
343}
344
345/*
346 * Internal function, do not call.
347 */
348static inline gp_list_head *gp_list_merge_sort(gp_list_head *head,
349 int (*cmp)(const void *, const void *))
350{
351 gp_list_head *middle, *tmp, *ret;
352
353 if (!head || !head->next)
354 return head;
355
356 for (middle = tmp = head; tmp; tmp = tmp->next) {
357 ret = middle;
358 middle = middle->next;
359 if (tmp->next)
360 tmp = tmp->next;
361 }
362
363 ret->next = NULL;
364 head = gp_list_merge_sort(head, cmp);
365 middle = gp_list_merge_sort(middle, cmp);
366
367 if (cmp(head, middle)) {
368 ret = tmp = head;
369 head = head->next;
370 } else {
371 ret = tmp = middle;
372 middle = middle->next;
373 }
374
375 while (head || middle) {
376 while (head && (!middle || cmp(middle, head) <= 0)) {
377 tmp->next = head;
378 tmp = head;
379 head = head->next;
380 }
381
382 while (middle && (!head || cmp(head, middle) <= 0)) {
383 tmp->next = middle;
384 tmp = middle;
385 middle = middle->next;
386 }
387 }
388
389 tmp->next = NULL;
390
391 return ret;
392}
393
420static inline void gp_list_sort(gp_list *list,
421 int (*cmp)(const void *, const void *))
422{
423 gp_list_head *tail;
424
425 if (!list->head)
426 return;
427
428 list->head = gp_list_merge_sort(list->head, cmp);
429
430 for (tail = list->head; tail->next; tail = tail->next);
431
432 list->tail = tail;
433}
434
443static inline void gp_dlist_sort(gp_dlist *list,
444 int (*cmp)(const void *, const void *))
445{
446 gp_dlist_head *i;
447
448 if (!list->head)
449 return;
450
451 list->head = (gp_dlist_head*)gp_list_merge_sort((gp_list_head*)list->head, cmp);
452
453 if (list->head)
454 list->head->prev = NULL;
455
456 for (i = list->head; i->next; i = i->next)
457 i->next->prev = i;
458
459 list->tail = i;
460}
461
462#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:199
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:214
static gp_dlist_head * gp_dlist_pop_head(gp_dlist *list)
Pops from a head of a double linked list.
Definition gp_list.h:283
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:236
static gp_list_head * gp_list_pop_head(gp_list *list)
Pops from a head of a linked list.
Definition gp_list.h:259
static void gp_list_push_tail(gp_list *list, gp_list_head *entry)
Pushes into tail of linked list.
Definition gp_list.h:186
static void gp_dlist_rem(gp_dlist *list, gp_dlist_head *entry)
Removes a entry from a double linked list.
Definition gp_list.h:330
static void gp_list_push_head(gp_list *list, gp_list_head *entry)
Pushes into head of linked list.
Definition gp_list.h:139
static void gp_dlist_push_head(gp_dlist *list, gp_dlist_head *entry)
Pushes into head of double linked list.
Definition gp_list.h:156
static gp_dlist_head * gp_dlist_pop_tail(gp_dlist *list)
Pops from a tail of a double linked list.
Definition gp_list.h:303
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:443
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:420
A double linked list header.
Definition gp_list.h:34
struct gp_dlist_head * prev
Pointer to previous list element.
Definition gp_list.h:38
struct gp_dlist_head * next
Pointer to next list element.
Definition gp_list.h:36
A double linked list pointers.
Definition gp_list.h:56
gp_dlist_head * head
A pointer to list head.
Definition gp_list.h:58
size_t cnt
A number of elements in the list.
Definition gp_list.h:62
gp_dlist_head * tail
A pointer to list tail.
Definition gp_list.h:60
A linked list header.
Definition gp_list.h:24
struct gp_list_head * next
Pointer to next list element.
Definition gp_list.h:26
A linked list pointers.
Definition gp_list.h:44
gp_list_head * tail
A pointer to list tail.
Definition gp_list.h:48
size_t cnt
A number of elements in the list.
Definition gp_list.h:50
gp_list_head * head
A pointer to list head.
Definition gp_list.h:46