annotate CSP2/CSP2_env/env-d9b9114564458d9d-741b3de822f2aaca6c6caa4325c4afce/include/tkDList.h @ 69:33d812a61356

planemo upload commit 2e9511a184a1ca667c7be0c6321a36dc4e3d116d
author jpayne
date Tue, 18 Mar 2025 17:55:14 -0400
parents
children
rev   line source
jpayne@69 1 /*
jpayne@69 2 * tkDList.h --
jpayne@69 3 *
jpayne@69 4 * A list is headed by pointers to first and last element. The elements
jpayne@69 5 * are doubly linked so that an arbitrary element can be removed without
jpayne@69 6 * a need to traverse the list. New elements can be added to the list
jpayne@69 7 * before or after an existing element or at the head/tail of the list.
jpayne@69 8 * A list may be traversed in the forward or backward direction.
jpayne@69 9 *
jpayne@69 10 * Copyright (c) 2018 by Gregor Cramer.
jpayne@69 11 *
jpayne@69 12 * See the file "license.terms" for information on usage and redistribution of
jpayne@69 13 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
jpayne@69 14 */
jpayne@69 15
jpayne@69 16 /*
jpayne@69 17 * Note that this file will not be included in header files, it is the purpose
jpayne@69 18 * of this file to be included in source files only. Thus we are not using the
jpayne@69 19 * prefix "Tk_" here for functions, because all the functions have private scope.
jpayne@69 20 */
jpayne@69 21
jpayne@69 22 /*
jpayne@69 23 * -------------------------------------------------------------------------------
jpayne@69 24 * Use the double linked list in the following way:
jpayne@69 25 * -------------------------------------------------------------------------------
jpayne@69 26 * typedef struct MyListEntry { TK_DLIST_LINKS(MyListEntry); int value; } MyListEntry;
jpayne@69 27 * TK_DLIST_DEFINE(MyList, MyListEntry);
jpayne@69 28 * MyList listHdr = TK_DLIST_LIST_INITIALIZER; // or MyList_Init(&listHdr)
jpayne@69 29 * MyListEntry *p;
jpayne@69 30 * int i = 0;
jpayne@69 31 * MyList_Append(&listHdr, ckalloc(sizeof(MyListEntry)));
jpayne@69 32 * MyList_Append(&listHdr, ckalloc(sizeof(MyListEntry)));
jpayne@69 33 * TK_DLIST_FOREACH(p, &listHdr) { p->value = i++; }
jpayne@69 34 * // ...
jpayne@69 35 * MyList_RemoveHead(&listHdr);
jpayne@69 36 * MyList_RemoveHead(&listHdr);
jpayne@69 37 * MyList_Clear(MyListEntry, &listHdr); // invokes ckfree() for each element
jpayne@69 38 * -------------------------------------------------------------------------------
jpayne@69 39 * IMPORTANT NOTE: TK_DLIST_LINKS must be used at start of struct!
jpayne@69 40 */
jpayne@69 41
jpayne@69 42 #ifndef TK_DLIST_DEFINED
jpayne@69 43 #define TK_DLIST_DEFINED
jpayne@69 44
jpayne@69 45 #include "tkInt.h"
jpayne@69 46
jpayne@69 47 /*
jpayne@69 48 * List definitions.
jpayne@69 49 */
jpayne@69 50
jpayne@69 51 #define TK_DLIST_LINKS(ElemType) \
jpayne@69 52 struct { \
jpayne@69 53 struct ElemType *prev; /* previous element */ \
jpayne@69 54 struct ElemType *next; /* next element */ \
jpayne@69 55 } _dl_
jpayne@69 56
jpayne@69 57 #define TK_DLIST_LIST_INITIALIZER { NULL, NULL }
jpayne@69 58 #define TK_DLIST_ELEM_INITIALIZER { NULL, NULL }
jpayne@69 59
jpayne@69 60 /*************************************************************************/
jpayne@69 61 /*
jpayne@69 62 * DList_Init: Initialize list header. This can also be used to clear the
jpayne@69 63 * list.
jpayne@69 64 *
jpayne@69 65 * See also: DList_Clear()
jpayne@69 66 */
jpayne@69 67 /*************************************************************************/
jpayne@69 68 /*
jpayne@69 69 * DList_ElemInit: Initialize a list element.
jpayne@69 70 */
jpayne@69 71 /*************************************************************************/
jpayne@69 72 /*
jpayne@69 73 * DList_InsertAfter: Insert 'elem' after 'listElem'. 'elem' must not
jpayne@69 74 * be linked, but 'listElem' must be linked.
jpayne@69 75 */
jpayne@69 76 /*************************************************************************/
jpayne@69 77 /*
jpayne@69 78 * DList_InsertBefore: Insert 'elem' before 'listElem'. 'elem' must not
jpayne@69 79 * be linked, but 'listElem' must be linked.
jpayne@69 80 */
jpayne@69 81 /*************************************************************************/
jpayne@69 82 /*
jpayne@69 83 * DList_Prepend: Insert 'elem' at start of list. This element must not
jpayne@69 84 * be linked.
jpayne@69 85 *
jpayne@69 86 * See also: DList_Append()
jpayne@69 87 */
jpayne@69 88 /*************************************************************************/
jpayne@69 89 /*
jpayne@69 90 * DList_Append: Append 'elem' to end of list. This element must not
jpayne@69 91 * be linked.
jpayne@69 92 *
jpayne@69 93 * See also: DList_Prepend()
jpayne@69 94 */
jpayne@69 95 /*************************************************************************/
jpayne@69 96 /*
jpayne@69 97 * DList_Move: Append all list items of 'src' to end of 'dst'.
jpayne@69 98 */
jpayne@69 99 /*************************************************************************/
jpayne@69 100 /*
jpayne@69 101 * DList_Remove: Remove 'elem' from list. This element must be linked.
jpayne@69 102 *
jpayne@69 103 * See also: DList_Free()
jpayne@69 104 */
jpayne@69 105 /*************************************************************************/
jpayne@69 106 /*
jpayne@69 107 * DList_Free: Remove 'elem' from list and free it. This element must
jpayne@69 108 * be linked.
jpayne@69 109 *
jpayne@69 110 * See also: DList_Remove()
jpayne@69 111 */
jpayne@69 112 /*************************************************************************/
jpayne@69 113 /*
jpayne@69 114 * DList_RemoveHead: Remove first element from list. The list must
jpayne@69 115 * not be empty.
jpayne@69 116 *
jpayne@69 117 * See also: DList_FreeHead()
jpayne@69 118 */
jpayne@69 119 /*************************************************************************/
jpayne@69 120 /*
jpayne@69 121 * DList_RemoveTail: Remove last element from list. The list must
jpayne@69 122 * not be empty.
jpayne@69 123 *
jpayne@69 124 * See also: DList_FreeTail()
jpayne@69 125 */
jpayne@69 126 /*************************************************************************/
jpayne@69 127 /*
jpayne@69 128 * DList_FreeHead: Remove first element from list and free it.
jpayne@69 129 * The list must not be empty.
jpayne@69 130 *
jpayne@69 131 * See also: DList_RemoveHead()
jpayne@69 132 */
jpayne@69 133 /*************************************************************************/
jpayne@69 134 /*
jpayne@69 135 * DList_FreeTail: Remove last element from list and free it.
jpayne@69 136 * The list must not be empty.
jpayne@69 137 *
jpayne@69 138 * See also: DList_RemoveTail()
jpayne@69 139 */
jpayne@69 140 /*************************************************************************/
jpayne@69 141 /*
jpayne@69 142 * DList_SwapElems: Swap positions of given elements 'lhs' and 'rhs'.
jpayne@69 143 * Both elements must be linked, and must belong to same list.
jpayne@69 144 */
jpayne@69 145 /*************************************************************************/
jpayne@69 146 /*
jpayne@69 147 * DList_Clear: Clear whole list and free all elements.
jpayne@69 148 *
jpayne@69 149 * See also: DList_Init
jpayne@69 150 */
jpayne@69 151 /*************************************************************************/
jpayne@69 152 /*
jpayne@69 153 * DList_Traverse: Iterate over all elements in list from first to last.
jpayne@69 154 * Call given function func(head, elem) for each element. The function has
jpayne@69 155 * to return the next element in list to traverse, normally this is
jpayne@69 156 * DList_Next(elem).
jpayne@69 157 *
jpayne@69 158 * See also: TK_DLIST_FOREACH, TK_DLIST_FOREACH_REVERSE
jpayne@69 159 */
jpayne@69 160 /*************************************************************************/
jpayne@69 161 /*
jpayne@69 162 * DList_First: Return pointer of first element in list, maybe it's NULL.
jpayne@69 163 */
jpayne@69 164 /*************************************************************************/
jpayne@69 165 /*
jpayne@69 166 * DList_Last: Return pointer of last element in list, maybe it's NULL.
jpayne@69 167 */
jpayne@69 168 /*************************************************************************/
jpayne@69 169 /*
jpayne@69 170 * DList_Next: Return pointer of next element after 'elem', maybe it's NULL.
jpayne@69 171 *
jpayne@69 172 * See also: DList_Prev()
jpayne@69 173 */
jpayne@69 174 /*************************************************************************/
jpayne@69 175 /*
jpayne@69 176 * DList_Prev: Return pointer of previous element before 'elem', maybe it's
jpayne@69 177 * NULL.
jpayne@69 178 *
jpayne@69 179 * See also: DList_Next()
jpayne@69 180 */
jpayne@69 181 /*************************************************************************/
jpayne@69 182 /*
jpayne@69 183 * DList_IsEmpty: Test whether given list is empty.
jpayne@69 184 */
jpayne@69 185 /*************************************************************************/
jpayne@69 186 /*
jpayne@69 187 * DList_IsLinked: Test whether given element is linked.
jpayne@69 188 */
jpayne@69 189 /*************************************************************************/
jpayne@69 190 /*
jpayne@69 191 * DList_IsFirst: Test whether given element is first element in list.
jpayne@69 192 * Note that 'elem' must be linked.
jpayne@69 193 *
jpayne@69 194 * See also: DList_IsLast(), DList_IsLinked()
jpayne@69 195 */
jpayne@69 196 /*************************************************************************/
jpayne@69 197 /*
jpayne@69 198 * DList_IsLast: Test whether given element is last element in list.
jpayne@69 199 * Note that 'elem' must be linked.
jpayne@69 200 *
jpayne@69 201 * See also: DList_IsFirst(), DList_IsLinked()
jpayne@69 202 */
jpayne@69 203 /*************************************************************************/
jpayne@69 204 /*
jpayne@69 205 * DList_Size: Count number of elements in given list.
jpayne@69 206 */
jpayne@69 207 /*************************************************************************/
jpayne@69 208 /*
jpayne@69 209 * TK_DLIST_FOREACH: Iterate over all elements in list from first to last.
jpayne@69 210 * 'var' is the name of the variable which points to current element.
jpayne@69 211 *
jpayne@69 212 * See also: TK_DLIST_FOREACH_REVERSE, DList_Traverse()
jpayne@69 213 */
jpayne@69 214 /*************************************************************************/
jpayne@69 215 /*
jpayne@69 216 * TK_DLIST_FOREACH_REVERSE: Iterate over all elements in list from last
jpayne@69 217 * to first (backwards). 'var' is the name of the variable which points to
jpayne@69 218 * current element.
jpayne@69 219 */
jpayne@69 220 /*************************************************************************/
jpayne@69 221
jpayne@69 222 #if defined(__GNUC__) || defined(__clang__)
jpayne@69 223 # define __TK_DLIST_UNUSED __attribute__((unused))
jpayne@69 224 #else
jpayne@69 225 # define __TK_DLIST_UNUSED
jpayne@69 226 #endif
jpayne@69 227
jpayne@69 228 #define TK_DLIST_DEFINE(LT, ElemType) /* LT = type of head/list */ \
jpayne@69 229 /* ------------------------------------------------------------------------- */ \
jpayne@69 230 typedef struct LT { \
jpayne@69 231 struct ElemType *first; /* first element */ \
jpayne@69 232 struct ElemType *last; /* last element */ \
jpayne@69 233 } LT; \
jpayne@69 234 \
jpayne@69 235 typedef struct ElemType *(LT##_Func)(LT *head, struct ElemType *elem); \
jpayne@69 236 \
jpayne@69 237 __TK_DLIST_UNUSED \
jpayne@69 238 static void \
jpayne@69 239 LT##_Init(LT *head) \
jpayne@69 240 { \
jpayne@69 241 assert(head); \
jpayne@69 242 head->first = NULL; \
jpayne@69 243 head->last = NULL; \
jpayne@69 244 } \
jpayne@69 245 \
jpayne@69 246 __TK_DLIST_UNUSED \
jpayne@69 247 static void \
jpayne@69 248 LT##_ElemInit(struct ElemType *elem) \
jpayne@69 249 { \
jpayne@69 250 assert(elem); \
jpayne@69 251 elem->_dl_.next = NULL; \
jpayne@69 252 elem->_dl_.prev = NULL; \
jpayne@69 253 } \
jpayne@69 254 \
jpayne@69 255 __TK_DLIST_UNUSED \
jpayne@69 256 static int \
jpayne@69 257 LT##_IsEmpty(LT *head) \
jpayne@69 258 { \
jpayne@69 259 assert(head); \
jpayne@69 260 return head->first == NULL; \
jpayne@69 261 } \
jpayne@69 262 \
jpayne@69 263 __TK_DLIST_UNUSED \
jpayne@69 264 static int \
jpayne@69 265 LT##_IsLinked(struct ElemType *elem) \
jpayne@69 266 { \
jpayne@69 267 assert(elem); \
jpayne@69 268 return elem->_dl_.next && elem->_dl_.prev; \
jpayne@69 269 } \
jpayne@69 270 \
jpayne@69 271 __TK_DLIST_UNUSED \
jpayne@69 272 static int \
jpayne@69 273 LT##_IsFirst(struct ElemType *elem) \
jpayne@69 274 { \
jpayne@69 275 assert(LT##_IsLinked(elem)); \
jpayne@69 276 return elem->_dl_.prev->_dl_.prev == elem; \
jpayne@69 277 } \
jpayne@69 278 \
jpayne@69 279 __TK_DLIST_UNUSED \
jpayne@69 280 static int \
jpayne@69 281 LT##_IsLast(struct ElemType *elem) \
jpayne@69 282 { \
jpayne@69 283 assert(LT##_IsLinked(elem)); \
jpayne@69 284 return elem->_dl_.next->_dl_.next == elem; \
jpayne@69 285 } \
jpayne@69 286 \
jpayne@69 287 __TK_DLIST_UNUSED \
jpayne@69 288 static struct ElemType * \
jpayne@69 289 LT##_First(LT *head) \
jpayne@69 290 { \
jpayne@69 291 assert(head); \
jpayne@69 292 return head->first; \
jpayne@69 293 } \
jpayne@69 294 \
jpayne@69 295 __TK_DLIST_UNUSED \
jpayne@69 296 static struct ElemType * \
jpayne@69 297 LT##_Last(LT *head) \
jpayne@69 298 { \
jpayne@69 299 assert(head); \
jpayne@69 300 return head->last; \
jpayne@69 301 } \
jpayne@69 302 \
jpayne@69 303 __TK_DLIST_UNUSED \
jpayne@69 304 static struct ElemType * \
jpayne@69 305 LT##_Next(struct ElemType *elem) \
jpayne@69 306 { \
jpayne@69 307 assert(elem); \
jpayne@69 308 return LT##_IsLast(elem) ? NULL : elem->_dl_.next; \
jpayne@69 309 } \
jpayne@69 310 \
jpayne@69 311 __TK_DLIST_UNUSED \
jpayne@69 312 static struct ElemType * \
jpayne@69 313 LT##_Prev(struct ElemType *elem) \
jpayne@69 314 { \
jpayne@69 315 assert(elem); \
jpayne@69 316 return LT##_IsFirst(elem) ? NULL : elem->_dl_.prev; \
jpayne@69 317 } \
jpayne@69 318 \
jpayne@69 319 __TK_DLIST_UNUSED \
jpayne@69 320 static unsigned \
jpayne@69 321 LT##_Size(const LT *head) \
jpayne@69 322 { \
jpayne@69 323 const struct ElemType *elem; \
jpayne@69 324 unsigned size = 0; \
jpayne@69 325 assert(head); \
jpayne@69 326 if ((elem = head->first)) { \
jpayne@69 327 for ( ; elem != (void *) head; elem = elem->_dl_.next) { \
jpayne@69 328 ++size; \
jpayne@69 329 } \
jpayne@69 330 } \
jpayne@69 331 return size; \
jpayne@69 332 } \
jpayne@69 333 \
jpayne@69 334 __TK_DLIST_UNUSED \
jpayne@69 335 static void \
jpayne@69 336 LT##_InsertAfter(struct ElemType *listElem, struct ElemType *elem) \
jpayne@69 337 { \
jpayne@69 338 assert(listElem); \
jpayne@69 339 assert(elem); \
jpayne@69 340 elem->_dl_.next = listElem->_dl_.next; \
jpayne@69 341 elem->_dl_.prev = listElem; \
jpayne@69 342 listElem->_dl_.next->_dl_.prev = elem; \
jpayne@69 343 listElem->_dl_.next = elem; \
jpayne@69 344 } \
jpayne@69 345 \
jpayne@69 346 __TK_DLIST_UNUSED \
jpayne@69 347 static void \
jpayne@69 348 LT##_InsertBefore(struct ElemType *listElem, struct ElemType *elem) \
jpayne@69 349 { \
jpayne@69 350 assert(listElem); \
jpayne@69 351 assert(elem); \
jpayne@69 352 elem->_dl_.next = listElem; \
jpayne@69 353 elem->_dl_.prev = listElem->_dl_.prev;; \
jpayne@69 354 listElem->_dl_.prev->_dl_.next = elem; \
jpayne@69 355 listElem->_dl_.prev = elem; \
jpayne@69 356 } \
jpayne@69 357 \
jpayne@69 358 __TK_DLIST_UNUSED \
jpayne@69 359 static void \
jpayne@69 360 LT##_Prepend(LT *head, struct ElemType *elem) \
jpayne@69 361 { \
jpayne@69 362 assert(head); \
jpayne@69 363 assert(elem); \
jpayne@69 364 elem->_dl_.prev = (void *) head; \
jpayne@69 365 if (!head->first) { \
jpayne@69 366 elem->_dl_.next = (void *) head; \
jpayne@69 367 head->last = elem; \
jpayne@69 368 } else { \
jpayne@69 369 elem->_dl_.next = head->first; \
jpayne@69 370 head->first->_dl_.prev = elem; \
jpayne@69 371 } \
jpayne@69 372 head->first = elem; \
jpayne@69 373 } \
jpayne@69 374 \
jpayne@69 375 __TK_DLIST_UNUSED \
jpayne@69 376 static void \
jpayne@69 377 LT##_Append(LT *head, struct ElemType *elem) \
jpayne@69 378 { \
jpayne@69 379 assert(head); \
jpayne@69 380 assert(elem); \
jpayne@69 381 elem->_dl_.next = (void *) head; \
jpayne@69 382 if (!head->first) { \
jpayne@69 383 elem->_dl_.prev = (void *) head; \
jpayne@69 384 head->first = elem; \
jpayne@69 385 } else { \
jpayne@69 386 elem->_dl_.prev = head->last; \
jpayne@69 387 head->last->_dl_.next = elem; \
jpayne@69 388 } \
jpayne@69 389 head->last = elem; \
jpayne@69 390 } \
jpayne@69 391 \
jpayne@69 392 __TK_DLIST_UNUSED \
jpayne@69 393 static void \
jpayne@69 394 LT##_Move(LT *dst, LT *src) \
jpayne@69 395 { \
jpayne@69 396 assert(dst); \
jpayne@69 397 assert(src); \
jpayne@69 398 if (src->first) { \
jpayne@69 399 if (dst->first) { \
jpayne@69 400 dst->last->_dl_.next = src->first; \
jpayne@69 401 src->first->_dl_.prev = dst->last; \
jpayne@69 402 dst->last = src->last; \
jpayne@69 403 } else { \
jpayne@69 404 *dst = *src; \
jpayne@69 405 dst->first->_dl_.prev = (void *) dst; \
jpayne@69 406 } \
jpayne@69 407 dst->last->_dl_.next = (void *) dst; \
jpayne@69 408 LT##_Init(src); \
jpayne@69 409 } \
jpayne@69 410 } \
jpayne@69 411 \
jpayne@69 412 __TK_DLIST_UNUSED \
jpayne@69 413 static void \
jpayne@69 414 LT##_Remove(struct ElemType *elem) \
jpayne@69 415 { \
jpayne@69 416 int isFirst, isLast; \
jpayne@69 417 assert(LT##_IsLinked(elem)); \
jpayne@69 418 isFirst = LT##_IsFirst(elem); \
jpayne@69 419 isLast = LT##_IsLast(elem); \
jpayne@69 420 if (isFirst && isLast) { \
jpayne@69 421 ((LT *) elem->_dl_.prev)->first = NULL; \
jpayne@69 422 ((LT *) elem->_dl_.next)->last = NULL; \
jpayne@69 423 } else { \
jpayne@69 424 if (isFirst) { \
jpayne@69 425 ((LT *) elem->_dl_.prev)->first = elem->_dl_.next; \
jpayne@69 426 } else { \
jpayne@69 427 elem->_dl_.prev->_dl_.next = elem->_dl_.next; \
jpayne@69 428 } \
jpayne@69 429 if (isLast) { \
jpayne@69 430 ((LT *) elem->_dl_.next)->last = elem->_dl_.prev; \
jpayne@69 431 } else { \
jpayne@69 432 elem->_dl_.next->_dl_.prev = elem->_dl_.prev; \
jpayne@69 433 } \
jpayne@69 434 } \
jpayne@69 435 LT##_ElemInit(elem); \
jpayne@69 436 } \
jpayne@69 437 \
jpayne@69 438 __TK_DLIST_UNUSED \
jpayne@69 439 static void \
jpayne@69 440 LT##_Free(struct ElemType *elem) \
jpayne@69 441 { \
jpayne@69 442 LT##_Remove(elem); \
jpayne@69 443 ckfree((void *) elem); \
jpayne@69 444 } \
jpayne@69 445 \
jpayne@69 446 __TK_DLIST_UNUSED \
jpayne@69 447 static void \
jpayne@69 448 LT##_RemoveHead(LT *head) \
jpayne@69 449 { \
jpayne@69 450 assert(!LT##_IsEmpty(head)); \
jpayne@69 451 LT##_Remove(head->first); \
jpayne@69 452 } \
jpayne@69 453 \
jpayne@69 454 __TK_DLIST_UNUSED \
jpayne@69 455 static void \
jpayne@69 456 LT##_RemoveTail(LT *head) \
jpayne@69 457 { \
jpayne@69 458 assert(!LT##_IsEmpty(head)); \
jpayne@69 459 LT##_Remove(head->last); \
jpayne@69 460 } \
jpayne@69 461 \
jpayne@69 462 __TK_DLIST_UNUSED \
jpayne@69 463 static void \
jpayne@69 464 LT##_FreeHead(LT *head) \
jpayne@69 465 { \
jpayne@69 466 assert(!LT##_IsEmpty(head)); \
jpayne@69 467 LT##_Free(head->first); \
jpayne@69 468 } \
jpayne@69 469 \
jpayne@69 470 __TK_DLIST_UNUSED \
jpayne@69 471 static void \
jpayne@69 472 LT##_FreeTail(LT *head) \
jpayne@69 473 { \
jpayne@69 474 assert(!LT##_IsEmpty(head)); \
jpayne@69 475 LT##_Free(head->last); \
jpayne@69 476 } \
jpayne@69 477 \
jpayne@69 478 __TK_DLIST_UNUSED \
jpayne@69 479 static void \
jpayne@69 480 LT##_SwapElems(struct ElemType *lhs, struct ElemType *rhs) \
jpayne@69 481 { \
jpayne@69 482 assert(lhs); \
jpayne@69 483 assert(rhs); \
jpayne@69 484 if (lhs != rhs) { \
jpayne@69 485 struct ElemType tmp; \
jpayne@69 486 if (LT##_IsFirst(lhs)) { \
jpayne@69 487 ((LT *) lhs->_dl_.prev)->first = rhs; \
jpayne@69 488 } else if (LT##_IsFirst(rhs)) { \
jpayne@69 489 ((LT *) rhs->_dl_.prev)->first = lhs; \
jpayne@69 490 } \
jpayne@69 491 if (LT##_IsLast(lhs)) { \
jpayne@69 492 ((LT *) lhs->_dl_.next)->last = rhs; \
jpayne@69 493 } else if (LT##_IsLast(rhs)) { \
jpayne@69 494 ((LT *) rhs->_dl_.next)->last = lhs; \
jpayne@69 495 } \
jpayne@69 496 tmp._dl_ = lhs->_dl_; \
jpayne@69 497 lhs->_dl_ = rhs->_dl_; \
jpayne@69 498 rhs->_dl_ = tmp._dl_; \
jpayne@69 499 } \
jpayne@69 500 } \
jpayne@69 501 \
jpayne@69 502 __TK_DLIST_UNUSED \
jpayne@69 503 static void \
jpayne@69 504 LT##_Clear(LT *head) \
jpayne@69 505 { \
jpayne@69 506 struct ElemType *p; \
jpayne@69 507 struct ElemType *next; \
jpayne@69 508 assert(head); \
jpayne@69 509 for (p = head->first; p; p = next) { \
jpayne@69 510 next = LT##_Next(p); \
jpayne@69 511 ckfree((void *) p); \
jpayne@69 512 } \
jpayne@69 513 LT##_Init(head); \
jpayne@69 514 } \
jpayne@69 515 \
jpayne@69 516 __TK_DLIST_UNUSED \
jpayne@69 517 static void \
jpayne@69 518 LT##_Traverse(LT *head, LT##_Func func) \
jpayne@69 519 { \
jpayne@69 520 struct ElemType *next; \
jpayne@69 521 struct ElemType *p; \
jpayne@69 522 assert(head); \
jpayne@69 523 for (p = head->first; p; p = next) { \
jpayne@69 524 next = func(head, p); \
jpayne@69 525 } \
jpayne@69 526 } \
jpayne@69 527 /* ------------------------------------------------------------------------- */
jpayne@69 528
jpayne@69 529 #define TK_DLIST_FOREACH(var, head) \
jpayne@69 530 assert(head); \
jpayne@69 531 for (var = head->first ? head->first : (void *) head; var != (void *) head; var = var->_dl_.next)
jpayne@69 532
jpayne@69 533 #define TK_DLIST_FOREACH_REVERSE(var, head) \
jpayne@69 534 assert(head); \
jpayne@69 535 for (var = head->last ? head->last : (void *) head; var != (void *) head; var = var->_dl_.prev)
jpayne@69 536
jpayne@69 537 #endif /* TK_DLIST_DEFINED */
jpayne@69 538
jpayne@69 539 /*
jpayne@69 540 * Local Variables:
jpayne@69 541 * mode: c
jpayne@69 542 * c-basic-offset: 4
jpayne@69 543 * fill-column: 105
jpayne@69 544 * End:
jpayne@69 545 * vi:set ts=8 sw=4:
jpayne@69 546 */