os-k/kaleid/include/extras/list.h

274 lines
5.4 KiB
C

//----------------------------------------------------------------------------//
// 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 <kalbase.h>
#endif
//------------------------------------------//
// Start of header //
//------------------------------------------//
#ifndef _KALEXTRAS_LIST_H
#define _KALEXTRAS_LIST_H
//
// XXX ¯\_(ツ)_/¯
//
#ifndef _STDLIB_H
void *malloc(long);
void free(void *);
#endif
#define AllocMemory malloc
#define FreeMemory free
//------------------------------------------//
// Data structures //
//------------------------------------------//
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;
//------------------------------------------//
// Functions //
//------------------------------------------//
//
// 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 liste 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)
//------------------------------------------//
// End of header //
//------------------------------------------//
#endif