mirror of
https://github.com/MikuLeaks/KianaBH3.git
synced 2025-12-14 05:44:34 +01:00
Init enter game
This commit is contained in:
212
KcpSharp/Base/NetstandardShim/LinkedListNetstandard.cs
Normal file
212
KcpSharp/Base/NetstandardShim/LinkedListNetstandard.cs
Normal file
@@ -0,0 +1,212 @@
|
||||
#if NEED_LINKEDLIST_SHIM
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace KcpSharp.NetstandardShim
|
||||
{
|
||||
internal class LinkedList<T>
|
||||
{
|
||||
// This LinkedList is a doubly-Linked circular list.
|
||||
internal LinkedListNode<T>? head;
|
||||
internal int count;
|
||||
internal int version;
|
||||
|
||||
public int Count
|
||||
{
|
||||
get { return count; }
|
||||
}
|
||||
|
||||
public LinkedListNode<T>? First
|
||||
{
|
||||
get { return head; }
|
||||
}
|
||||
|
||||
public LinkedListNode<T>? Last
|
||||
{
|
||||
get { return head == null ? null : head.prev; }
|
||||
}
|
||||
|
||||
public void AddAfter(LinkedListNode<T> node, LinkedListNode<T> newNode)
|
||||
{
|
||||
ValidateNode(node);
|
||||
ValidateNewNode(newNode);
|
||||
InternalInsertNodeBefore(node.next!, newNode);
|
||||
newNode.list = this;
|
||||
}
|
||||
|
||||
public void AddBefore(LinkedListNode<T> node, LinkedListNode<T> newNode)
|
||||
{
|
||||
ValidateNode(node);
|
||||
ValidateNewNode(newNode);
|
||||
InternalInsertNodeBefore(node, newNode);
|
||||
newNode.list = this;
|
||||
if (node == head)
|
||||
{
|
||||
head = newNode;
|
||||
}
|
||||
}
|
||||
|
||||
public void AddFirst(LinkedListNode<T> node)
|
||||
{
|
||||
ValidateNewNode(node);
|
||||
|
||||
if (head == null)
|
||||
{
|
||||
InternalInsertNodeToEmptyList(node);
|
||||
}
|
||||
else
|
||||
{
|
||||
InternalInsertNodeBefore(head, node);
|
||||
head = node;
|
||||
}
|
||||
node.list = this;
|
||||
}
|
||||
|
||||
public void AddLast(LinkedListNode<T> node)
|
||||
{
|
||||
ValidateNewNode(node);
|
||||
|
||||
if (head == null)
|
||||
{
|
||||
InternalInsertNodeToEmptyList(node);
|
||||
}
|
||||
else
|
||||
{
|
||||
InternalInsertNodeBefore(head, node);
|
||||
}
|
||||
node.list = this;
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
LinkedListNode<T>? current = head;
|
||||
while (current != null)
|
||||
{
|
||||
LinkedListNode<T> temp = current;
|
||||
current = current.Next; // use Next the instead of "next", otherwise it will loop forever
|
||||
temp.Invalidate();
|
||||
}
|
||||
|
||||
head = null;
|
||||
count = 0;
|
||||
version++;
|
||||
}
|
||||
|
||||
public void Remove(LinkedListNode<T> node)
|
||||
{
|
||||
ValidateNode(node);
|
||||
InternalRemoveNode(node);
|
||||
}
|
||||
|
||||
public void RemoveFirst()
|
||||
{
|
||||
if (head == null) { throw new InvalidOperationException(); }
|
||||
InternalRemoveNode(head);
|
||||
}
|
||||
|
||||
private void InternalInsertNodeBefore(LinkedListNode<T> node, LinkedListNode<T> newNode)
|
||||
{
|
||||
newNode.next = node;
|
||||
newNode.prev = node.prev;
|
||||
node.prev!.next = newNode;
|
||||
node.prev = newNode;
|
||||
version++;
|
||||
count++;
|
||||
}
|
||||
|
||||
private void InternalInsertNodeToEmptyList(LinkedListNode<T> newNode)
|
||||
{
|
||||
Debug.Assert(head == null && count == 0, "LinkedList must be empty when this method is called!");
|
||||
newNode.next = newNode;
|
||||
newNode.prev = newNode;
|
||||
head = newNode;
|
||||
version++;
|
||||
count++;
|
||||
}
|
||||
|
||||
internal void InternalRemoveNode(LinkedListNode<T> node)
|
||||
{
|
||||
Debug.Assert(node.list == this, "Deleting the node from another list!");
|
||||
Debug.Assert(head != null, "This method shouldn't be called on empty list!");
|
||||
if (node.next == node)
|
||||
{
|
||||
Debug.Assert(count == 1 && head == node, "this should only be true for a list with only one node");
|
||||
head = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
node.next!.prev = node.prev;
|
||||
node.prev!.next = node.next;
|
||||
if (head == node)
|
||||
{
|
||||
head = node.next;
|
||||
}
|
||||
}
|
||||
node.Invalidate();
|
||||
count--;
|
||||
version++;
|
||||
}
|
||||
|
||||
internal static void ValidateNewNode(LinkedListNode<T> node)
|
||||
{
|
||||
if (node == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(node));
|
||||
}
|
||||
|
||||
if (node.list != null)
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
internal void ValidateNode(LinkedListNode<T> node)
|
||||
{
|
||||
if (node == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(node));
|
||||
}
|
||||
|
||||
if (node.list != this)
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Note following class is not serializable since we customized the serialization of LinkedList.
|
||||
internal sealed class LinkedListNode<T>
|
||||
{
|
||||
internal LinkedList<T>? list;
|
||||
internal LinkedListNode<T>? next;
|
||||
internal LinkedListNode<T>? prev;
|
||||
internal T item;
|
||||
|
||||
public LinkedListNode(T value)
|
||||
{
|
||||
item = value;
|
||||
}
|
||||
|
||||
public LinkedListNode<T>? Next
|
||||
{
|
||||
get { return next == null || next == list!.head ? null : next; }
|
||||
}
|
||||
|
||||
public LinkedListNode<T>? Previous
|
||||
{
|
||||
get { return prev == null || this == list!.head ? null : prev; }
|
||||
}
|
||||
|
||||
/// <summary>Gets a reference to the value held by the node.</summary>
|
||||
public ref T ValueRef => ref item;
|
||||
|
||||
internal void Invalidate()
|
||||
{
|
||||
list = null;
|
||||
next = null;
|
||||
prev = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user