using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace DCFApixels.DragonECS.Graphs.Internal
{
internal class EntityLinkedList
{
public const int Enter = 0;
internal Node[] _nodes;
private int _count;
private int _lastNodeIndex;
#region Properties
public int Count => _count;
public int Capacity => _nodes.Length;
public int Last => _lastNodeIndex;
#endregion
#region Constructors
public EntityLinkedList(int capacity)
{
_nodes = new Node[capacity + 10];
Clear();
}
#endregion
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Resize(int newCapacity)
{
Array.Resize(ref _nodes, newCapacity + 10);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Clear()
{
for (int i = 0; i < _nodes.Length; i++)
{
_nodes[i].next = 0;
}
_lastNodeIndex = Enter;
_count = 0;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Set(int nodeIndex, int entityID)
{
_nodes[nodeIndex].entityID = entityID;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public int Get(int nodeIndex)
{
return _nodes[nodeIndex].entityID;
}
/// Insert after
/// new node index
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public int InsertAfter(int nodeIndex, int entityID)
{
_nodes[++_count].Set(entityID, _nodes[nodeIndex].next);
_nodes[nodeIndex].next = _count;
_lastNodeIndex = _count;
return _count;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public int Add(int entityID)
{
return InsertAfter(_lastNodeIndex, entityID);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Enumerator GetEnumerator()
{
return new Enumerator(_nodes);
}
//[MethodImpl(MethodImplOptions.AggressiveInlining)]
//public EcsJoinedSpan GetSpan(int startNodeIndex, int count)
//{
// return new EcsJoinedSpan(_nodes, startNodeIndex, count);
//}
//[MethodImpl(MethodImplOptions.AggressiveInlining)]
//public EcsJoinedSpan GetEmptySpan()
//{
// return new EcsJoinedSpan(_nodes, 0, 0);
//}
#region Utils
[StructLayout(LayoutKind.Sequential, Pack = 4, Size = 8)]
public struct Node
{
public static readonly Node Empty = new Node() { entityID = 0, next = -1 };
public int entityID;
/// next node index
public int next;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Set(int entityID, int next)
{
this.entityID = entityID;
this.next = next;
}
}
public struct Enumerator
{
private readonly Node[] _nodes;
private int _index;
private int _next;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Enumerator(Node[] nodes)
{
_nodes = nodes;
_index = -1;
_next = Enter;
}
public int Current
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get { return _nodes[_index].entityID; }
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool MoveNext()
{
_index = _next;
_next = _nodes[_next].next;
return _index > 0;
}
}
#endregion
}
}