mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 20:11:17 +00:00
170 lines
2.9 KiB
C
170 lines
2.9 KiB
C
// Copyright (c) 2021 Christoffer Lerno. All rights reserved.
|
|
// Use of this source code is governed by the MIT license
|
|
// a copy of which can be found in the LICENSE_STDLIB file.
|
|
module std::array::linkedlist<Type>;
|
|
|
|
private struct Node
|
|
{
|
|
Node *next;
|
|
Node *prev;
|
|
Type value;
|
|
}
|
|
|
|
struct LinkedList
|
|
{
|
|
usize size;
|
|
Node *first;
|
|
Node *last;
|
|
}
|
|
|
|
fn void LinkedList.push(LinkedList *list, Type value)
|
|
{
|
|
list.linkLast(value);
|
|
}
|
|
|
|
private fn void LinkedList.linkFirst(LinkedList *list, Type value)
|
|
{
|
|
Node *first = list.first;
|
|
Node *new_node = mem::malloc(Node);
|
|
*new_node = { .next = first, .value = value };
|
|
list.first = new_node;
|
|
if (!first)
|
|
{
|
|
list.last = new_node;
|
|
}
|
|
else
|
|
{
|
|
first.prev = new_node;
|
|
}
|
|
list.size++;
|
|
}
|
|
|
|
private fn void LinkedList.linkLast(LinkedList *list, Type value)
|
|
{
|
|
Node *last = list.last;
|
|
Node *new_node = mem::alloc(Node.sizeof);
|
|
*new_node = { .prev = last, .value = value };
|
|
list.last = new_node;
|
|
if (!last)
|
|
{
|
|
list.first = new_node;
|
|
}
|
|
else
|
|
{
|
|
last.next = new_node;
|
|
}
|
|
list.size++;
|
|
}
|
|
|
|
fn void LinkedList.free(LinkedList *list)
|
|
{
|
|
for (Node* node = list.first; node != null;)
|
|
{
|
|
Node* next = node.next;
|
|
mem::free(node);
|
|
node = next;
|
|
}
|
|
list.first = null;
|
|
list.last = null;
|
|
list.size = 0;
|
|
}
|
|
|
|
fn usize LinkedList.len(LinkedList* list) @inline
|
|
{
|
|
return list.size;
|
|
}
|
|
|
|
fn Type LinkedList.get(LinkedList* list, usize index)
|
|
{
|
|
Node* node = list.first;
|
|
while (index--)
|
|
{
|
|
node = node.next;
|
|
}
|
|
return node.value;
|
|
}
|
|
/**
|
|
* @require succ != null
|
|
**/
|
|
private fn void LinkedList.linkBefore(LinkedList *list, Node *succ, Type value)
|
|
{
|
|
Node* pred = succ.prev;
|
|
Node* new_node = mem::malloc(Node);
|
|
*new_node = { .prev = pred, .next = succ, .value = value };
|
|
succ.prev = new_node;
|
|
if (!pred)
|
|
{
|
|
list.first = new_node;
|
|
}
|
|
else
|
|
{
|
|
pred.next = new_node;
|
|
}
|
|
list.size++;
|
|
}
|
|
|
|
/**
|
|
* @require f == list.first && f != null
|
|
**/
|
|
private fn void unlinkFirst(LinkedList* list, Node* f)
|
|
{
|
|
Node* next = f.next;
|
|
mem::free(f);
|
|
list.first = next;
|
|
if (!next)
|
|
{
|
|
list.last = null;
|
|
}
|
|
else
|
|
{
|
|
next.prev = null;
|
|
}
|
|
list.size--;
|
|
}
|
|
|
|
/**
|
|
* @require l == list.last && l != null
|
|
**/
|
|
private fn void LinkedList.unlinkLast(LinkedList *list, Node* l)
|
|
{
|
|
Node* prev = l.prev;
|
|
list.last = prev;
|
|
mem::free(l);
|
|
if (!prev)
|
|
{
|
|
list.first = null;
|
|
}
|
|
else
|
|
{
|
|
prev.next = null;
|
|
}
|
|
list.size--;
|
|
}
|
|
|
|
/**
|
|
* @require x != null
|
|
**/
|
|
private fn void LinkedList.unlink(LinkedList* list, Node* x)
|
|
{
|
|
Node* next = x.next;
|
|
Node* prev = x.prev;
|
|
if (!prev)
|
|
{
|
|
list.first = next;
|
|
}
|
|
else
|
|
{
|
|
prev.next = next;
|
|
}
|
|
if (!next)
|
|
{
|
|
list.last = prev;
|
|
}
|
|
else
|
|
{
|
|
next.prev = prev;
|
|
}
|
|
mem::free(x);
|
|
list.size--;
|
|
}
|