DragonECS/src/Internal/ArrayUtility.cs
2026-03-16 22:57:16 +08:00

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()))}}})";
}
}
}