mirror of
https://github.com/DCFApixels/DragonECS.git
synced 2026-04-22 01:45:55 +08:00
284 lines
9.4 KiB
C#
284 lines
9.4 KiB
C#
#if DISABLE_DEBUG
|
|
#undef DEBUG
|
|
#endif
|
|
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Runtime.CompilerServices;
|
|
|
|
namespace DCFApixels.DragonECS.Core.Internal
|
|
{
|
|
internal interface ILinkedNext
|
|
{
|
|
int Next { get; }
|
|
}
|
|
internal readonly struct LinkedListCountIterator<T> : IEnumerable<T>
|
|
where T : ILinkedNext
|
|
{
|
|
public readonly T[] Array;
|
|
public readonly int Count;
|
|
public readonly int StartIndex;
|
|
public LinkedListCountIterator(T[] array, int count, int startIndex)
|
|
{
|
|
Array = array;
|
|
Count = count;
|
|
StartIndex = startIndex;
|
|
}
|
|
public Enumerator GetEnumerator()
|
|
{
|
|
return new Enumerator(Array, Count, StartIndex);
|
|
}
|
|
IEnumerator<T> IEnumerable<T>.GetEnumerator() { return GetEnumerator(); }
|
|
IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); }
|
|
public struct Enumerator : IEnumerator<T>
|
|
{
|
|
private readonly T[] _array;
|
|
private readonly int _count;
|
|
private int _index;
|
|
private int _counter;
|
|
public Enumerator(T[] array, int count, int index)
|
|
{
|
|
_array = array;
|
|
_count = count;
|
|
_index = index;
|
|
_counter = 0;
|
|
}
|
|
public ref T Current
|
|
{
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
get { return ref _array[_index]; }
|
|
}
|
|
T IEnumerator<T>.Current { get { return _array[_index]; } }
|
|
object IEnumerator.Current { get { return Current; } }
|
|
public bool MoveNext()
|
|
{
|
|
if (++_counter > _count) { return false; }
|
|
if (_counter > 1)
|
|
{
|
|
_index = _array[_index].Next;
|
|
}
|
|
return true;
|
|
}
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
void IDisposable.Dispose() { }
|
|
void IEnumerator.Reset() { throw new NotSupportedException(); }
|
|
}
|
|
}
|
|
internal readonly struct LinkedListIterator<T> : IEnumerable<T>
|
|
where T : ILinkedNext
|
|
{
|
|
public readonly T[] Array;
|
|
public readonly int EndIndex;
|
|
public readonly int StartIndex;
|
|
public LinkedListIterator(T[] array, int endIndex, int startIndex)
|
|
{
|
|
Array = array;
|
|
EndIndex = endIndex;
|
|
StartIndex = startIndex;
|
|
}
|
|
public Enumerator GetEnumerator()
|
|
{
|
|
return new Enumerator(Array, EndIndex, StartIndex);
|
|
}
|
|
IEnumerator<T> IEnumerable<T>.GetEnumerator() { return GetEnumerator(); }
|
|
IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); }
|
|
public struct Enumerator : IEnumerator<T>
|
|
{
|
|
private readonly T[] _array;
|
|
private readonly int _endIndex;
|
|
private readonly int _startIndex;
|
|
private int _nextIndex;
|
|
private int _index;
|
|
public ref T Current { get { return ref _array[_index]; } }
|
|
T IEnumerator<T>.Current { get { return Current; } }
|
|
object IEnumerator.Current { get { return Current; } }
|
|
public Enumerator(T[] array, int endIndex, int head)
|
|
{
|
|
_array = array;
|
|
_startIndex = head;
|
|
_nextIndex = _startIndex;
|
|
_endIndex = endIndex;
|
|
_index = _endIndex;
|
|
}
|
|
public bool MoveNext()
|
|
{
|
|
if (_nextIndex < 0) { return false; }
|
|
_index = _nextIndex;
|
|
_nextIndex = _array[_index].Next;
|
|
return true;
|
|
}
|
|
public void Dispose() { }
|
|
public void Reset()
|
|
{
|
|
_nextIndex = _startIndex;
|
|
_index = _endIndex;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
internal static class ArrayUtility
|
|
{
|
|
public static void ResizeOrCreate<T>(ref T[] array, int newSize)
|
|
{
|
|
if (array == null)
|
|
{
|
|
array = new T[newSize];
|
|
}
|
|
{
|
|
Array.Resize(ref array, newSize);
|
|
}
|
|
}
|
|
internal static void UpsizeTwoHead<T>(ref T[] array, int newLength, int separationIndex)
|
|
{
|
|
UpsizeTwoHead(ref array, newLength, separationIndex, array.Length - separationIndex);
|
|
}
|
|
internal static void UpsizeTwoHead<T>(ref T[] array, int newLength, int leftHeadLength, int rightHeadLength)
|
|
{
|
|
if (array.Length > newLength) { return; }
|
|
var result = new T[newLength];
|
|
Array.Copy(array, result, leftHeadLength); // copy left head
|
|
Array.Copy(array, array.Length - rightHeadLength, result, array.Length - rightHeadLength, rightHeadLength); // copy right head
|
|
array = result;
|
|
}
|
|
|
|
public static int NextPow2Safe(int v, int min = 4)
|
|
{
|
|
return NextPow2(v < min ? min : v);
|
|
}
|
|
public static int NextPow2(int v)
|
|
{
|
|
return CeilPow2(v | 1);
|
|
}
|
|
public static int CeilPow2Safe(int v, int min = 4)
|
|
{
|
|
return CeilPow2(v < min ? min : v);
|
|
}
|
|
public static int CeilPow2(int v)
|
|
{
|
|
unchecked
|
|
{
|
|
v--;
|
|
v |= v >> 1;
|
|
v |= v >> 2;
|
|
v |= v >> 4;
|
|
v |= v >> 8;
|
|
v |= v >> 16;
|
|
return ++v;
|
|
}
|
|
}
|
|
public static int CeilPow2_ClampOverflow(int v)
|
|
{
|
|
unchecked
|
|
{
|
|
const int NO_SIGN_HIBIT = 0x40000000;
|
|
if ((v & NO_SIGN_HIBIT) != 0)
|
|
{
|
|
return int.MaxValue;
|
|
}
|
|
return CeilPow2(v);
|
|
}
|
|
}
|
|
|
|
public static void Fill<T>(T[] array, T value, int startIndex = 0, int length = -1)
|
|
{
|
|
if (length < 0)
|
|
{
|
|
length = array.Length;
|
|
}
|
|
else
|
|
{
|
|
length = startIndex + length;
|
|
}
|
|
for (int i = startIndex; i < length; i++)
|
|
{
|
|
array[i] = value;
|
|
}
|
|
}
|
|
|
|
|
|
public static void UpsizeWithoutCopy<T>(ref T[] array, int minSize)
|
|
{
|
|
if (array == null || minSize > array.Length)
|
|
{
|
|
array = new T[minSize];
|
|
}
|
|
}
|
|
public static void Upsize<T>(ref T[] array, int minSize)
|
|
{
|
|
if (array == null)
|
|
{
|
|
array = new T[minSize];
|
|
}
|
|
else if (minSize > array.Length)
|
|
{
|
|
Array.Resize(ref array, minSize);
|
|
}
|
|
}
|
|
//public static void UpsizeToCeilPow2<T>(ref T[] array, int newSize, int minSize = 4)
|
|
//{
|
|
// newSize = CeilPow2(newSize < minSize ? minSize : newSize);
|
|
// if (array == null)
|
|
// {
|
|
// array = new T[newSize];
|
|
// }
|
|
// else if (newSize > array.Length)
|
|
// {
|
|
// Array.Resize(ref array, newSize);
|
|
// }
|
|
//}
|
|
}
|
|
internal readonly struct EnumerableInt : IEnumerable<int>
|
|
{
|
|
public readonly int start;
|
|
public readonly int length;
|
|
private EnumerableInt(int start, int length)
|
|
{
|
|
this.start = start;
|
|
this.length = length;
|
|
}
|
|
public static EnumerableInt Range(int start, int length) { return new EnumerableInt(start, length); }
|
|
public static EnumerableInt StartEnd(int start, int end) { return new EnumerableInt(start, end - start); }
|
|
IEnumerator<int> IEnumerable<int>.GetEnumerator() { return GetEnumerator(); }
|
|
IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); }
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public Enumerator GetEnumerator() { return new Enumerator(start, start + length); }
|
|
public struct Enumerator : IEnumerator<int>
|
|
{
|
|
private readonly int _max;
|
|
private int _current;
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public Enumerator(int max, int current)
|
|
{
|
|
_max = max;
|
|
_current = current - 1;
|
|
}
|
|
public int Current
|
|
{
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
get { return _current; }
|
|
}
|
|
object IEnumerator.Current { get { return Current; } }
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public bool MoveNext() { return ++_current < _max; }
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
void IDisposable.Dispose() { }
|
|
void IEnumerator.Reset() { throw new NotSupportedException(); }
|
|
|
|
}
|
|
}
|
|
|
|
public static class CollectionUtility
|
|
{
|
|
public static string EntitiesToString(IEnumerable<int> range, string name)
|
|
{
|
|
return $"{name}({range.Count()}) {{{string.Join(", ", range.OrderBy(o => o))}}})";
|
|
}
|
|
public static string AutoToString<T>(IEnumerable<T> range, string name)
|
|
{
|
|
return $"{name}({range.Count()}) {{{string.Join(", ", range.Select(o => o.ToString()))}}})";
|
|
}
|
|
}
|
|
} |