//----------------------------------------------------------------------------// // GNU GPL OS/K // // // // Authors: spectral` // // NeoX // // // // Desc: Doubly linked lists implementation // //----------------------------------------------------------------------------// #ifdef _KALEID_KERNEL #error "extra/list.h - Not ready for kernel compilation" #endif #ifndef _KALBASE_H #include #endif #ifndef _KALEXTRAS_MALLOC_H #include #endif #ifndef _KALEXTRAS_LIST_H #define _KALEXTRAS_LIST_H //------------------------------------------// typedef struct sListHead_t { Lock_t *lock; unsigned long length; struct sListNode_t *first; struct sListNode_t *last; } ListHead_t; typedef struct sListNode_t { void *data; ListHead_t *head; struct sListNode_t *prev; struct sListNode_t *next; } ListNode_t; //------------------------------------------// // // Create a list head with an extern lock // static inline ListHead_t *CreateListHeadWithLock(Lock_t *lock) { ListHead_t *head = AllocMemory(sizeof(ListHead_t)); if (head == NULL) return NULL; head->first = head->last = NULL; head->length = 0; head->lock = lock; return head; } // // Create a list head // static inline ListHead_t *CreateListHead(void) { return CreateListHeadWithLock(NULL); } // // Create a node // static inline ListNode_t *CreateNode(void *data) { ListNode_t *node = AllocMemory(sizeof(ListNode_t)); if (node == NULL) return NULL; node->data = data; node->head = NULL; node->prev = node->next = NULL; return node; } // // Prepend node at beginning of list // static inline ListHead_t *PrependNode(ListHead_t *head, ListNode_t *node) { KalAssert(head && node); node->head = head; node->prev = NULL; if (head->length > 0) { node->next = head->first; head->first->prev = node; head->first = node; } else { head->first = node; head->last = node; node->next = NULL; } head->length++; return head; } // // Append node at end of list // static inline ListHead_t *AppendNode(ListHead_t *head, ListNode_t *node) { KalAssert(head && node); node->head = head; node->next = NULL; if (head->length > 0) { node->prev = head->last; head->last->next = node; head->last = node; } else { head->first = node; head->last = node; node->prev = NULL; } head->length++; return head; } // // Insert node2 before node1 // static inline ListHead_t *AddNodeBefore(ListHead_t *head, ListNode_t *node1, ListNode_t *node2) { KalAssert(head && node1 && node2 && node1->head == head); if (head->first == node1) { return PrependNode(head, node2); } node2->head = head; node2->next = node1; node2->prev = node1->prev; // node1->prev does exist // or node1 would be first node1->prev->next = node2; node1->prev = node2; head->length++; return head; } // // Insert node2 after node1 // static inline ListHead_t *AddNodeAfter(ListHead_t *head, ListNode_t *node1, ListNode_t *node2) { KalAssert(head && node1 && node2 && node1->head == head); if (head->last == node1) { return AppendNode(head, node2); } node2->head = head; node2->prev = node1; node2->next = node1->next; node1->next->prev = node2; node1->next = node2; head->length++; return head; } // // Remove node of list (and frees it) // static inline ListHead_t *RemoveNode(ListHead_t *head, ListNode_t *node) { KalAssert(head && node && head->length > 0 && node->head == head); if (head->length == 1) { head->first = head->last = NULL; goto leave; } if (head->first == node) { head->first = node->next; node->next->prev = NULL; } else if (head->last == node) { head->last = node->prev; node->prev->next = NULL; } else { node->prev->next = node->next; node->next->prev = node->prev; } leave: head->length--; FreeMemory(node); return head; } // // Free a node // static inline void DestroyNode(ListNode_t *node) { KalAssert(node); FreeMemory(node); } // // Free a list head // static inline void DestroyListHead(ListHead_t *head) { KalAssert(head); FreeMemory(head); } // // Access a node's data // #define GetNodeData(node, type) ((type)(node)->data) //------------------------------------------// #endif