\ head->first = NULL; \ head->last = NULL; \ } \ \ __TK_DLIST_UNUSED \ static void \ LT##_ElemInit(struct ElemType *elem) \ { \ assert(elem); \ elem->_dl_.next = NULL; \ elem->_dl_.prev = NULL; \ } \ \ __TK_DLIST_UNUSED \ static int \ LT##_IsEmpty(LT *head) \ { \ assert(head); \ return head->first == NULL; \ } \ \ __TK_DLIST_UNUSED \ static int \ LT##_IsLinked(struct ElemType *elem) \ { \ assert(elem); \ return elem->_dl_.next && elem->_dl_.prev; \ } \ \ __TK_DLIST_UNUSED \ static int \ LT##_IsFirst(struct ElemType *elem) \ { \ assert(LT##_IsLinked(elem)); \ return elem->_dl_.prev->_dl_.prev == elem; \ } \ \ __TK_DLIST_UNUSED \ static int \ LT##_IsLast(struct ElemType *elem) \ { \ assert(LT##_IsLinked(elem)); \ return elem->_dl_.next->_dl_.next == elem; \ } \ \ __TK_DLIST_UNUSED \ static struct ElemType * \ LT##_First(LT *head) \ { \ assert(head); \ return head->first; \ } \ \ __TK_DLIST_UNUSED \ static struct ElemType * \ LT##_Last(LT *head) \ { \ assert(head); \ return head->last; \ } \ \ __TK_DLIST_UNUSED \ static struct ElemType * \ LT##_Next(struct ElemType *elem) \ { \ assert(elem); \ return LT##_IsLast(elem) ? NULL : elem->_dl_.next; \ } \ \ __TK_DLIST_UNUSED \ static struct ElemType * \ LT##_Prev(struct ElemType *elem) \ { \ assert(elem); \ return LT##_IsFirst(elem) ? NULL : elem->_dl_.prev; \ } \ \ __TK_DLIST_UNUSED \ static unsigned \ LT##_Size(const LT *head) \ { \ const struct ElemType *elem; \ unsigned size = 0; \ assert(head); \ if ((elem = head->first)) { \ for ( ; elem != (void *) head; elem = elem->_dl_.next) { \ ++size; \ } \ } \ return size; \ } \ \ __TK_DLIST_UNUSED \ static void \ LT##_InsertAfter(struct ElemType *listElem, struct ElemType *elem) \ { \ assert(listElem); \ assert(elem); \ elem->_dl_.next = listElem->_dl_.next; \ elem->_dl_.prev = listElem; \ listElem->_dl_.next->_dl_.prev = elem; \ listElem->_dl_.next = elem; \ } \ \ __TK_DLIST_UNUSED \ static void \ LT##_InsertBefore(struct ElemType *listElem, struct ElemType *elem) \ { \ assert(listElem); \ assert(elem); \ elem->_dl_.next = listElem; \ elem->_dl_.prev = listElem->_dl_.prev;; \ listElem->_dl_.prev->_dl_.next = elem; \ listElem->_dl_.prev = elem; \ } \ \ __TK_DLIST_UNUSED \ static void \ LT##_Prepend(LT *head, struct ElemType *elem) \ { \ assert(head); \ assert(elem); \ elem->_dl_.prev = (void *) head; \ if (!head->first) { \ elem->_dl_.next = (void *) head; \ head->last = elem; \ } else { \ elem->_dl_.next = head->first; \ head->first->_dl_.prev = elem; \ } \ head->first = elem; \ } \ \ __TK_DLIST_UNUSED \ static void \ LT##_Append(LT *head, struct ElemType *elem) \ { \ assert(head); \ assert(elem); \ elem->_dl_.next = (void *) head; \ if (!head->first) { \ elem->_dl_.prev = (void *) head; \ head->first = elem; \ } else { \ elem->_dl_.prev = head->last; \ head->last->_dl_.next = elem; \ } \ head->last = elem; \ } \ \ __TK_DLIST_UNUSED \ static void \ LT##_Move(LT *dst, LT *src) \ { \ assert(dst); \ assert(src); \ if (src->first) { \ if (dst->first) { \ dst->last->_dl_.next = src->first; \ src->first->_dl_.prev = dst->last; \ dst->last = src->last; \ } else { \ *dst = *src; \ dst->first->_dl_.prev = (void *) dst; \ } \ dst->last->_dl_.next = (void *) dst; \ LT##_Init(src); \ } \ } \ \ __TK_DLIST_UNUSED \ static void \ LT##_Remove(struct ElemType *elem) \ { \ int isFirst, isLast; \ assert(LT##_IsLinked(elem)); \ isFirst = LT##_IsFirst(elem); \ isLast = LT##_IsLast(elem); \ if (isFirst && isLast) { \ ((LT *) elem->_dl_.prev)->first = NULL; \ ((LT *) elem->_dl_.next)->last = NULL; \ } else { \ if (isFirst) { \ ((LT *) elem->_dl_.prev)->first = elem->_dl_.next; \ } else { \ elem->_dl_.prev->_dl_.next = elem->_dl_.next; \ } \ if (isLast) { \ ((LT *) elem->_dl_.next)->last = elem->_dl_.prev; \ } else { \ elem->_dl_.next->_dl_.prev = elem->_dl_.prev; \ } \ } \ LT##_ElemInit(elem); \ } \ \ __TK_DLIST_UNUSED \ static void \ LT##_Free(struct ElemType *elem) \ { \ LT##_Remove(elem); \ ckfree((void *) elem); \ } \ \ __TK_DLIST_UNUSED \ static void \ LT##_RemoveHead(LT *head) \ { \ assert(!LT##_IsEmpty(head)); \ LT##_Remove(head->first); \ } \ \ __TK_DLIST_UNUSED \ static void \ LT##_RemoveTail(LT *head) \ { \ assert(!LT##_IsEmpty(head)); \ LT##_Remove(head->last); \ } \ \ __TK_DLIST_UNUSED \ static void \ LT##_FreeHead(LT *head) \ { \ assert(!LT##_IsEmpty(head)); \ LT##_Free(head->first); \ } \ \ __TK_DLIST_UNUSED \ static void \ LT##_FreeTail(LT *head) \ { \ assert(!LT##_IsEmpty(head)); \ LT##_Free(head->last); \ } \ \ __TK_DLIST_UNUSED \ static void \ LT##_SwapElems(struct ElemType *lhs, struct ElemType *rhs) \ { \ assert(lhs); \ assert(rhs); \ if (lhs != rhs) { \ struct ElemType tmp; \ if (LT##_IsFirst(lhs)) { \ ((LT *) lhs->_dl_.prev)->first = rhs; \ } else if (LT##_IsFirst(rhs)) { \ ((LT *) rhs->_dl_.prev)->first = lhs; \ } \ if (LT##_IsLast(lhs)) { \ ((LT *) lhs->_dl_.next)->last = rhs; \ } else if (LT##_IsLast(rhs)) { \ ((LT *) rhs->_dl_.next)->last = lhs; \ } \ tmp._dl_ = lhs->_dl_; \ lhs->_dl_ = rhs->_dl_; \ rhs->_dl_ = tmp._dl_; \ } \ } \ \ __TK_DLIST_UNUSED \ static void \ LT##_Clear(LT *head) \ { \ struct ElemType *p; \ struct ElemType *next; \ assert(head); \ for (p = head->first; p; p = next) { \ next = LT##_Next(p); \ ckfree((void *) p); \ } \ LT##_Init(head); \ } \ \ __TK_DLIST_UNUSED \ static void \ LT##_Traverse(LT *head, LT##_Func func) \ { \ struct ElemType *next; \ struct ElemType *p; \ assert(head); \ for (p = head->first; p; p = next) { \ next = func(head, p); \ } \ } \ /* ------------------------------------------------------------------------- */ #define TK_DLIST_FOREACH(var, head) \ assert(head); \ for (var = head->first ? head->first : (void *) head; var != (void *) head; var = var->_dl_.next) #define TK_DLIST_FOREACH_REVERSE(var, head) \ assert(head); \ for (var = head->last ? head->last : (void *) head; var != (void *) head; var = var->_dl_.prev)