00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifndef ISC_LIST_H
00021 #define ISC_LIST_H 1
00022 #include <isc/boolean.h>
00023 #include <isc/assertions.h>
00024
00025 #ifdef ISC_LIST_CHECKINIT
00026 #define ISC_LINK_INSIST(x) ISC_INSIST(x)
00027 #else
00028 #define ISC_LINK_INSIST(x)
00029 #endif
00030
00031 #define ISC_LIST(type) struct { type *head, *tail; }
00032 #define ISC_LIST_INIT(list) \
00033 do { (list).head = NULL; (list).tail = NULL; } while (0)
00034
00035 #define ISC_LINK(type) struct { type *prev, *next; }
00036 #define ISC_LINK_INIT_TYPE(elt, link, type) \
00037 do { \
00038 (elt)->link.prev = (type *)(-1); \
00039 (elt)->link.next = (type *)(-1); \
00040 } while (0)
00041 #define ISC_LINK_INIT(elt, link) \
00042 ISC_LINK_INIT_TYPE(elt, link, void)
00043 #define ISC_LINK_LINKED(elt, link) ((void *)((elt)->link.prev) != (void *)(-1))
00044
00045 #define ISC_LIST_HEAD(list) ((list).head)
00046 #define ISC_LIST_TAIL(list) ((list).tail)
00047 #define ISC_LIST_EMPTY(list) ISC_TF((list).head == NULL)
00048
00049 #define __ISC_LIST_PREPENDUNSAFE(list, elt, link) \
00050 do { \
00051 if ((list).head != NULL) \
00052 (list).head->link.prev = (elt); \
00053 else \
00054 (list).tail = (elt); \
00055 (elt)->link.prev = NULL; \
00056 (elt)->link.next = (list).head; \
00057 (list).head = (elt); \
00058 } while (0)
00059
00060 #define ISC_LIST_PREPEND(list, elt, link) \
00061 do { \
00062 ISC_LINK_INSIST(!ISC_LINK_LINKED(elt, link)); \
00063 __ISC_LIST_PREPENDUNSAFE(list, elt, link); \
00064 } while (0)
00065
00066 #define ISC_LIST_INITANDPREPEND(list, elt, link) \
00067 __ISC_LIST_PREPENDUNSAFE(list, elt, link)
00068
00069 #define __ISC_LIST_APPENDUNSAFE(list, elt, link) \
00070 do { \
00071 if ((list).tail != NULL) \
00072 (list).tail->link.next = (elt); \
00073 else \
00074 (list).head = (elt); \
00075 (elt)->link.prev = (list).tail; \
00076 (elt)->link.next = NULL; \
00077 (list).tail = (elt); \
00078 } while (0)
00079
00080 #define ISC_LIST_APPEND(list, elt, link) \
00081 do { \
00082 ISC_LINK_INSIST(!ISC_LINK_LINKED(elt, link)); \
00083 __ISC_LIST_APPENDUNSAFE(list, elt, link); \
00084 } while (0)
00085
00086 #define ISC_LIST_INITANDAPPEND(list, elt, link) \
00087 __ISC_LIST_APPENDUNSAFE(list, elt, link)
00088
00089 #define __ISC_LIST_UNLINKUNSAFE_TYPE(list, elt, link, type) \
00090 do { \
00091 if ((elt)->link.next != NULL) \
00092 (elt)->link.next->link.prev = (elt)->link.prev; \
00093 else { \
00094 ISC_INSIST((list).tail == (elt)); \
00095 (list).tail = (elt)->link.prev; \
00096 } \
00097 if ((elt)->link.prev != NULL) \
00098 (elt)->link.prev->link.next = (elt)->link.next; \
00099 else { \
00100 ISC_INSIST((list).head == (elt)); \
00101 (list).head = (elt)->link.next; \
00102 } \
00103 (elt)->link.prev = (type *)(-1); \
00104 (elt)->link.next = (type *)(-1); \
00105 ISC_INSIST((list).head != (elt)); \
00106 ISC_INSIST((list).tail != (elt)); \
00107 } while (0)
00108
00109 #define __ISC_LIST_UNLINKUNSAFE(list, elt, link) \
00110 __ISC_LIST_UNLINKUNSAFE_TYPE(list, elt, link, void)
00111
00112 #define ISC_LIST_UNLINK_TYPE(list, elt, link, type) \
00113 do { \
00114 ISC_LINK_INSIST(ISC_LINK_LINKED(elt, link)); \
00115 __ISC_LIST_UNLINKUNSAFE_TYPE(list, elt, link, type); \
00116 } while (0)
00117 #define ISC_LIST_UNLINK(list, elt, link) \
00118 ISC_LIST_UNLINK_TYPE(list, elt, link, void)
00119
00120 #define ISC_LIST_PREV(elt, link) ((elt)->link.prev)
00121 #define ISC_LIST_NEXT(elt, link) ((elt)->link.next)
00122
00123 #define __ISC_LIST_INSERTBEFOREUNSAFE(list, before, elt, link) \
00124 do { \
00125 if ((before)->link.prev == NULL) \
00126 ISC_LIST_PREPEND(list, elt, link); \
00127 else { \
00128 (elt)->link.prev = (before)->link.prev; \
00129 (before)->link.prev = (elt); \
00130 (elt)->link.prev->link.next = (elt); \
00131 (elt)->link.next = (before); \
00132 } \
00133 } while (0)
00134
00135 #define ISC_LIST_INSERTBEFORE(list, before, elt, link) \
00136 do { \
00137 ISC_LINK_INSIST(ISC_LINK_LINKED(before, link)); \
00138 ISC_LINK_INSIST(!ISC_LINK_LINKED(elt, link)); \
00139 __ISC_LIST_INSERTBEFOREUNSAFE(list, before, elt, link); \
00140 } while (0)
00141
00142 #define __ISC_LIST_INSERTAFTERUNSAFE(list, after, elt, link) \
00143 do { \
00144 if ((after)->link.next == NULL) \
00145 ISC_LIST_APPEND(list, elt, link); \
00146 else { \
00147 (elt)->link.next = (after)->link.next; \
00148 (after)->link.next = (elt); \
00149 (elt)->link.next->link.prev = (elt); \
00150 (elt)->link.prev = (after); \
00151 } \
00152 } while (0)
00153
00154 #define ISC_LIST_INSERTAFTER(list, after, elt, link) \
00155 do { \
00156 ISC_LINK_INSIST(ISC_LINK_LINKED(after, link)); \
00157 ISC_LINK_INSIST(!ISC_LINK_LINKED(elt, link)); \
00158 __ISC_LIST_INSERTAFTERUNSAFE(list, after, elt, link); \
00159 } while (0)
00160
00161 #define ISC_LIST_APPENDLIST(list1, list2, link) \
00162 do { \
00163 if (ISC_LIST_EMPTY(list1)) \
00164 (list1) = (list2); \
00165 else if (!ISC_LIST_EMPTY(list2)) { \
00166 (list1).tail->link.next = (list2).head; \
00167 (list2).head->link.prev = (list1).tail; \
00168 (list1).tail = (list2).tail; \
00169 } \
00170 (list2).head = NULL; \
00171 (list2).tail = NULL; \
00172 } while (0)
00173
00174 #define ISC_LIST_PREPENDLIST(list1, list2, link) \
00175 do { \
00176 if (ISC_LIST_EMPTY(list1)) \
00177 (list1) = (list2); \
00178 else if (!ISC_LIST_EMPTY(list2)) { \
00179 (list2).tail->link.next = (list1).head; \
00180 (list1).head->link.prev = (list2).tail; \
00181 (list1).head = (list2).head; \
00182 } \
00183 (list2).head = NULL; \
00184 (list2).tail = NULL; \
00185 } while (0)
00186
00187 #define ISC_LIST_ENQUEUE(list, elt, link) ISC_LIST_APPEND(list, elt, link)
00188 #define __ISC_LIST_ENQUEUEUNSAFE(list, elt, link) \
00189 __ISC_LIST_APPENDUNSAFE(list, elt, link)
00190 #define ISC_LIST_DEQUEUE(list, elt, link) \
00191 ISC_LIST_UNLINK_TYPE(list, elt, link, void)
00192 #define ISC_LIST_DEQUEUE_TYPE(list, elt, link, type) \
00193 ISC_LIST_UNLINK_TYPE(list, elt, link, type)
00194 #define __ISC_LIST_DEQUEUEUNSAFE(list, elt, link) \
00195 __ISC_LIST_UNLINKUNSAFE_TYPE(list, elt, link, void)
00196 #define __ISC_LIST_DEQUEUEUNSAFE_TYPE(list, elt, link, type) \
00197 __ISC_LIST_UNLINKUNSAFE_TYPE(list, elt, link, type)
00198
00199 #endif