//----------------------------------------------------------------------------// // GNU GPL OS/K // // // // Desc: Doubly linked lists implementation // // // // // // Copyright © 2018-2019 The OS/K Team // // // // This file is part of OS/K. // // // // OS/K is free software: you can redistribute it and/or modify // // it under the terms of the GNU General Public License as published by // // the Free Software Foundation, either version 3 of the License, or // // any later version. // // // // OS/K is distributed in the hope that it will be useful, // // but WITHOUT ANY WARRANTY//without even the implied warranty of // // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // // GNU General Public License for more details. // // // // You should have received a copy of the GNU General Public License // // along with OS/K. If not, see . // //----------------------------------------------------------------------------// #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_LOCKS_H #include #endif #ifndef _KALEXTRAS_LIST_H #define _KALEXTRAS_LIST_H #ifdef __cplusplus extern "C" { #endif typedef struct ListHead_t ListHead_t; typedef struct ListNode_t ListNode_t; //------------------------------------------// struct ListHead_t { Lock_t *lock; ulong length; ListNode_t *first; ListNode_t *last; }; struct ListNode_t { void *data; ListHead_t *head; ListNode_t *prev; ListNode_t *next; }; //------------------------------------------// // // Create a list head with an extern lock // static inline ListHead_t *ExCreateListHeadWithLock(Lock_t *lock) { ListHead_t *head = KalAllocMemory(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 *ExCreateListHead(void) { return ExCreateListHeadWithLock(NULL); } // // Create a node // static inline ListNode_t *ExCreateNode(void *data) { ListNode_t *node = KalAllocMemory(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 *ExPrependNode(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 *ExAppendNode(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 *ExAddNodeBefore(ListHead_t *head, ListNode_t *node1, ListNode_t *node2) { KalAssert(head && node1 && node2 && node1->head == head); if (head->first == node1) { return ExPrependNode(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 *ExAddNodeAfter(ListHead_t *head, ListNode_t *node1, ListNode_t *node2) { KalAssert(head && node1 && node2 && node1->head == head); if (head->last == node1) { return ExAppendNode(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 *ExRemoveNode(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--; KalFreeMemory(node); return head; } // // Free a node // static inline void ExDestroyNode(ListNode_t *node) { KalAssert(node); KalFreeMemory(node); } // // Free a list head // static inline void ExDestroyListHead(ListHead_t *head) { KalAssert(head); KalFreeMemory(head); } // // Access a node's data // #define ExGetNodeData(node, type) ((type)(node)->data) //------------------------------------------// #ifdef __cplusplus } #endif #endif