1 /* 2 * Copyright (C) Internet Systems Consortium, Inc. ("ISC") 3 * 4 * This Source Code Form is subject to the terms of the Mozilla Public 5 * License, v. 2.0. If a copy of the MPL was not distributed with this 6 * file, you can obtain one at https://mozilla.org/MPL/2.0/. 7 * 8 * See the COPYRIGHT file distributed with this work for additional 9 * information regarding copyright ownership. 10 */ 11 12 #ifndef LWRES_LIST_H 13 #define LWRES_LIST_H 1 14 15 /*! \file lwres/list.h */ 16 17 #define LWRES_LIST(type) struct { type *head, *tail; } 18 #define LWRES_LIST_INIT(list) \ 19 do { (list).head = NULL; (list).tail = NULL; } while (0) 20 21 #define LWRES_LINK(type) struct { type *prev, *next; } 22 #define LWRES_LINK_INIT(elt, link) \ 23 do { \ 24 (elt)->link.prev = (void *)(-1); \ 25 (elt)->link.next = (void *)(-1); \ 26 } while (0) 27 #define LWRES_LINK_LINKED(elt, link) \ 28 ((void *)((elt)->link.prev) != (void *)(-1)) 29 30 #define LWRES_LIST_HEAD(list) ((list).head) 31 #define LWRES_LIST_TAIL(list) ((list).tail) 32 #define LWRES_LIST_EMPTY(list) LWRES_TF((list).head == NULL) 33 34 #define LWRES_LIST_PREPEND(list, elt, link) \ 35 do { \ 36 if ((list).head != NULL) \ 37 (list).head->link.prev = (elt); \ 38 else \ 39 (list).tail = (elt); \ 40 (elt)->link.prev = NULL; \ 41 (elt)->link.next = (list).head; \ 42 (list).head = (elt); \ 43 } while (0) 44 45 #define LWRES_LIST_APPEND(list, elt, link) \ 46 do { \ 47 if ((list).tail != NULL) \ 48 (list).tail->link.next = (elt); \ 49 else \ 50 (list).head = (elt); \ 51 (elt)->link.prev = (list).tail; \ 52 (elt)->link.next = NULL; \ 53 (list).tail = (elt); \ 54 } while (0) 55 56 #define LWRES_LIST_UNLINK(list, elt, link) \ 57 do { \ 58 if ((elt)->link.next != NULL) \ 59 (elt)->link.next->link.prev = (elt)->link.prev; \ 60 else \ 61 (list).tail = (elt)->link.prev; \ 62 if ((elt)->link.prev != NULL) \ 63 (elt)->link.prev->link.next = (elt)->link.next; \ 64 else \ 65 (list).head = (elt)->link.next; \ 66 (elt)->link.prev = (void *)(-1); \ 67 (elt)->link.next = (void *)(-1); \ 68 } while (0) 69 70 #define LWRES_LIST_PREV(elt, link) ((elt)->link.prev) 71 #define LWRES_LIST_NEXT(elt, link) ((elt)->link.next) 72 73 #define LWRES_LIST_INSERTBEFORE(list, before, elt, link) \ 74 do { \ 75 if ((before)->link.prev == NULL) \ 76 LWRES_LIST_PREPEND(list, elt, link); \ 77 else { \ 78 (elt)->link.prev = (before)->link.prev; \ 79 (before)->link.prev = (elt); \ 80 (elt)->link.prev->link.next = (elt); \ 81 (elt)->link.next = (before); \ 82 } \ 83 } while (0) 84 85 #define LWRES_LIST_INSERTAFTER(list, after, elt, link) \ 86 do { \ 87 if ((after)->link.next == NULL) \ 88 LWRES_LIST_APPEND(list, elt, link); \ 89 else { \ 90 (elt)->link.next = (after)->link.next; \ 91 (after)->link.next = (elt); \ 92 (elt)->link.next->link.prev = (elt); \ 93 (elt)->link.prev = (after); \ 94 } \ 95 } while (0) 96 97 #define LWRES_LIST_APPENDLIST(list1, list2, link) \ 98 do { \ 99 if (LWRES_LIST_EMPTY(list1)) \ 100 (list1) = (list2); \ 101 else if (!LWRES_LIST_EMPTY(list2)) { \ 102 (list1).tail->link.next = (list2).head; \ 103 (list2).head->link.prev = (list1).tail; \ 104 (list1).tail = (list2).tail; \ 105 } \ 106 (list2).head = NULL; \ 107 (list2).tail = NULL; \ 108 } while (0) 109 110 #define LWRES_LIST_ENQUEUE(list, elt, link) LWRES_LIST_APPEND(list, elt, link) 111 #define LWRES_LIST_DEQUEUE(list, elt, link) LWRES_LIST_UNLINK(list, elt, link) 112 113 #endif /* LWRES_LIST_H */ 114