//----------------------------------------------------------------------------// // 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 <https://www.gnu.org/licenses/>. // //----------------------------------------------------------------------------// #ifndef _LIBC_H #include <libc.h> #endif #ifndef _LIB_LIST_H #define _LIB_LIST_H #ifdef __cplusplus extern "C" { #endif typedef struct ListHead_t ListHead_t; typedef struct ListNode_t ListNode_t; //------------------------------------------// struct ListHead_t { ulong length; ListNode_t *first; ListNode_t *last; }; struct ListNode_t { ListHead_t *head; ListNode_t *prev; ListNode_t *next; }; //------------------------------------------// // // Create a list head with an extern lock // static inline ListHead_t *ExCreateListHead() { ListHead_t *head = malloc(sizeof(ListHead_t)); if (head == NULL) return NULL; head->first = head->last = NULL; head->length = 0; return head; } static inline ListNode_t *ExCreateNode() { ListNode_t *node = malloc(sizeof(ListNode_t)); if (node == NULL) return NULL; node->prev = node->next = NULL; node->head = NULL; return node; } // // Prepend node at beginning of list // static inline ListHead_t *ExPrependNode(ListHead_t *head, ListNode_t *node) { assert(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) { assert(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) { assert(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) { assert(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) { assert(head); assert(node); assert(head->length > 0); assert(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--; free(node); return head; } // // Free a list head // static inline void ExDestroyListHead(ListHead_t *head) { assert(head); free(head); } #define ExGetNodeData(list, type) ((type)list) //------------------------------------------// #ifdef __cplusplus } #endif #endif