2024-01-05 23:49:29 +08:00
|
|
|
|
using System;
|
2024-01-07 18:52:54 +08:00
|
|
|
|
using System.Collections;
|
2024-01-05 23:49:29 +08:00
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Runtime.CompilerServices;
|
2023-12-24 18:11:20 +08:00
|
|
|
|
using System.Runtime.InteropServices;
|
|
|
|
|
|
2024-02-07 22:16:41 +08:00
|
|
|
|
namespace DCFApixels.DragonECS.Internal
|
2023-04-08 00:47:35 +08:00
|
|
|
|
{
|
2024-09-05 17:27:09 +08:00
|
|
|
|
internal interface ILinkedNext
|
|
|
|
|
{
|
|
|
|
|
int Next { get; }
|
|
|
|
|
}
|
|
|
|
|
internal readonly struct LinkedListIterator<T> : IEnumerable<T>
|
|
|
|
|
where T : ILinkedNext
|
|
|
|
|
{
|
|
|
|
|
public readonly T[] Array;
|
|
|
|
|
public readonly int Count;
|
|
|
|
|
public readonly int StartIndex;
|
|
|
|
|
public LinkedListIterator(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;
|
|
|
|
|
}
|
2024-09-07 17:18:35 +08:00
|
|
|
|
public ref T Current
|
|
|
|
|
{
|
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
|
|
|
get { return ref _array[_index]; }
|
|
|
|
|
}
|
2024-09-05 17:27:09 +08:00
|
|
|
|
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;
|
|
|
|
|
}
|
2024-09-07 17:18:35 +08:00
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
|
|
|
void IDisposable.Dispose() { }
|
|
|
|
|
void IEnumerator.Reset() { throw new NotSupportedException(); }
|
2024-09-05 17:27:09 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
2024-09-07 17:18:35 +08:00
|
|
|
|
|
2023-04-08 00:47:35 +08:00
|
|
|
|
internal static class ArrayUtility
|
|
|
|
|
{
|
2024-02-07 22:16:41 +08:00
|
|
|
|
private static int GetHighBitNumber(uint bits)
|
|
|
|
|
{
|
|
|
|
|
if (bits == 0)
|
|
|
|
|
{
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
int bit = 0;
|
|
|
|
|
if ((bits & 0xFFFF0000) != 0)
|
|
|
|
|
{
|
|
|
|
|
bits >>= 16;
|
|
|
|
|
bit |= 16;
|
|
|
|
|
}
|
|
|
|
|
if ((bits & 0xFF00) != 0)
|
|
|
|
|
{
|
|
|
|
|
bits >>= 8;
|
|
|
|
|
bit |= 8;
|
|
|
|
|
}
|
|
|
|
|
if ((bits & 0xF0) != 0)
|
|
|
|
|
{
|
|
|
|
|
bits >>= 4;
|
|
|
|
|
bit |= 4;
|
|
|
|
|
}
|
|
|
|
|
if ((bits & 0xC) != 0)
|
|
|
|
|
{
|
|
|
|
|
bits >>= 2;
|
|
|
|
|
bit |= 2;
|
|
|
|
|
}
|
|
|
|
|
if ((bits & 0x2) != 0)
|
|
|
|
|
{
|
|
|
|
|
bit |= 1;
|
|
|
|
|
}
|
|
|
|
|
return bit;
|
|
|
|
|
}
|
|
|
|
|
public static int NormalizeSizeToPowerOfTwo(int minSize)
|
|
|
|
|
{
|
2024-02-13 21:00:01 +08:00
|
|
|
|
unchecked
|
|
|
|
|
{
|
|
|
|
|
return 1 << (GetHighBitNumber((uint)minSize - 1u) + 1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
public static int NormalizeSizeToPowerOfTwo_ClampOverflow(int minSize)
|
|
|
|
|
{
|
|
|
|
|
unchecked
|
|
|
|
|
{
|
|
|
|
|
int hibit = (GetHighBitNumber((uint)minSize - 1u) + 1);
|
|
|
|
|
if (hibit >= 32)
|
|
|
|
|
{
|
|
|
|
|
return int.MaxValue;
|
|
|
|
|
}
|
|
|
|
|
return 1 << hibit;
|
|
|
|
|
}
|
2024-02-07 22:16:41 +08:00
|
|
|
|
}
|
2023-04-08 00:47:35 +08:00
|
|
|
|
public static void Fill<T>(T[] array, T value, int startIndex = 0, int length = -1)
|
|
|
|
|
{
|
|
|
|
|
if (length < 0)
|
2024-02-07 22:16:41 +08:00
|
|
|
|
{
|
2023-04-08 00:47:35 +08:00
|
|
|
|
length = array.Length;
|
2024-02-07 22:16:41 +08:00
|
|
|
|
}
|
2023-04-08 00:47:35 +08:00
|
|
|
|
else
|
2024-02-07 22:16:41 +08:00
|
|
|
|
{
|
2023-04-08 00:47:35 +08:00
|
|
|
|
length = startIndex + length;
|
2024-02-07 22:16:41 +08:00
|
|
|
|
}
|
2023-04-08 00:47:35 +08:00
|
|
|
|
for (int i = startIndex; i < length; i++)
|
2024-02-07 22:16:41 +08:00
|
|
|
|
{
|
2023-04-08 00:47:35 +08:00
|
|
|
|
array[i] = value;
|
2024-02-07 22:16:41 +08:00
|
|
|
|
}
|
2023-04-08 00:47:35 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
2024-01-07 18:52:54 +08:00
|
|
|
|
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;
|
|
|
|
|
}
|
2024-09-07 17:18:35 +08:00
|
|
|
|
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(); }
|
2024-01-07 18:52:54 +08:00
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
2024-09-07 17:18:35 +08:00
|
|
|
|
public Enumerator GetEnumerator() { return new Enumerator(start, start + length); }
|
2024-01-07 18:52:54 +08:00
|
|
|
|
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)]
|
2024-09-07 17:18:35 +08:00
|
|
|
|
get { return _current; }
|
2024-01-07 18:52:54 +08:00
|
|
|
|
}
|
2024-09-07 17:18:35 +08:00
|
|
|
|
object IEnumerator.Current { get { return Current; } }
|
2023-12-24 18:11:20 +08:00
|
|
|
|
|
2024-01-07 18:52:54 +08:00
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
2024-09-07 17:18:35 +08:00
|
|
|
|
public bool MoveNext() { return ++_current < _max; }
|
2024-01-07 18:52:54 +08:00
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
2024-09-07 17:18:35 +08:00
|
|
|
|
void IDisposable.Dispose() { }
|
|
|
|
|
void IEnumerator.Reset() { throw new NotSupportedException(); }
|
|
|
|
|
|
2024-01-07 18:52:54 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
2023-12-24 18:11:20 +08:00
|
|
|
|
internal static unsafe class UnmanagedArrayUtility
|
|
|
|
|
{
|
2024-02-23 18:34:40 +08:00
|
|
|
|
private static class MetaCache<T>
|
|
|
|
|
{
|
|
|
|
|
public readonly static int Size;
|
|
|
|
|
static MetaCache()
|
|
|
|
|
{
|
|
|
|
|
T def = default;
|
|
|
|
|
Size = Marshal.SizeOf(def);
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-12-24 18:11:20 +08:00
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
2023-12-31 17:58:20 +08:00
|
|
|
|
public static T* New<T>(int capacity) where T : unmanaged
|
2023-12-24 18:11:20 +08:00
|
|
|
|
{
|
2023-12-31 17:58:20 +08:00
|
|
|
|
return (T*)Marshal.AllocHGlobal(Marshal.SizeOf<T>() * capacity).ToPointer();
|
2023-12-24 18:11:20 +08:00
|
|
|
|
}
|
2024-01-07 18:52:54 +08:00
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
|
|
|
public static void New<T>(out T* ptr, int capacity) where T : unmanaged
|
|
|
|
|
{
|
|
|
|
|
ptr = (T*)Marshal.AllocHGlobal(Marshal.SizeOf<T>() * capacity).ToPointer();
|
|
|
|
|
}
|
2023-12-24 18:11:20 +08:00
|
|
|
|
|
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
2023-12-31 17:58:20 +08:00
|
|
|
|
public static T* NewAndInit<T>(int capacity) where T : unmanaged
|
2023-12-24 18:11:20 +08:00
|
|
|
|
{
|
2024-02-23 18:34:40 +08:00
|
|
|
|
int newSize = MetaCache<T>.Size * capacity;
|
2023-12-24 18:11:20 +08:00
|
|
|
|
byte* newPointer = (byte*)Marshal.AllocHGlobal(newSize).ToPointer();
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < newSize; i++)
|
|
|
|
|
*(newPointer + i) = 0;
|
|
|
|
|
|
2023-12-31 17:58:20 +08:00
|
|
|
|
return (T*)newPointer;
|
2023-12-24 18:11:20 +08:00
|
|
|
|
}
|
2024-01-07 18:52:54 +08:00
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
|
|
|
public static void NewAndInit<T>(out T* ptr, int capacity) where T : unmanaged
|
|
|
|
|
{
|
2024-02-23 18:34:40 +08:00
|
|
|
|
int newSize = MetaCache<T>.Size * capacity;
|
2024-01-07 18:52:54 +08:00
|
|
|
|
byte* newPointer = (byte*)Marshal.AllocHGlobal(newSize).ToPointer();
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < newSize; i++)
|
|
|
|
|
*(newPointer + i) = 0;
|
|
|
|
|
|
|
|
|
|
ptr = (T*)newPointer;
|
|
|
|
|
}
|
2023-12-24 18:11:20 +08:00
|
|
|
|
|
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
|
|
|
public static void Free(void* pointer)
|
|
|
|
|
{
|
|
|
|
|
Marshal.FreeHGlobal(new IntPtr(pointer));
|
|
|
|
|
}
|
2024-01-07 18:52:54 +08:00
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
|
|
|
public static void Free<T>(ref T* pointer, ref int length) where T : unmanaged
|
|
|
|
|
{
|
|
|
|
|
Marshal.FreeHGlobal(new IntPtr(pointer));
|
|
|
|
|
pointer = null;
|
|
|
|
|
length = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
|
|
|
public static T* Clone<T>(T* sourcePtr, int length) where T : unmanaged
|
|
|
|
|
{
|
|
|
|
|
T* clone = New<T>(length);
|
|
|
|
|
for (int i = 0; i < length; i++)
|
2024-02-07 22:16:41 +08:00
|
|
|
|
{
|
2024-01-07 18:52:54 +08:00
|
|
|
|
clone[i] = sourcePtr[i];
|
2024-02-07 22:16:41 +08:00
|
|
|
|
}
|
2024-01-07 18:52:54 +08:00
|
|
|
|
return clone;
|
|
|
|
|
}
|
2023-12-24 18:11:20 +08:00
|
|
|
|
|
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
2023-12-31 17:58:20 +08:00
|
|
|
|
public static T* Resize<T>(void* oldPointer, int newCount) where T : unmanaged
|
2023-12-24 18:11:20 +08:00
|
|
|
|
{
|
2023-12-31 17:58:20 +08:00
|
|
|
|
return (T*)(Marshal.ReAllocHGlobal(
|
2023-12-24 18:11:20 +08:00
|
|
|
|
new IntPtr(oldPointer),
|
2024-02-23 18:34:40 +08:00
|
|
|
|
new IntPtr(MetaCache<T>.Size * newCount))).ToPointer();
|
2023-12-24 18:11:20 +08:00
|
|
|
|
}
|
2024-11-03 18:57:56 +08:00
|
|
|
|
|
|
|
|
|
|
2023-12-24 18:11:20 +08:00
|
|
|
|
}
|
2024-01-05 23:49:29 +08:00
|
|
|
|
|
2024-01-07 18:52:54 +08:00
|
|
|
|
public static class CollectionUtility
|
2024-01-05 23:49:29 +08:00
|
|
|
|
{
|
2024-01-07 18:52:54 +08:00
|
|
|
|
public static string EntitiesToString(IEnumerable<int> range, string name)
|
2024-01-05 23:49:29 +08:00
|
|
|
|
{
|
|
|
|
|
return $"{name}({range.Count()}) {{{string.Join(", ", range.OrderBy(o => o))}}})";
|
|
|
|
|
}
|
2024-01-07 18:52:54 +08:00
|
|
|
|
public static string AutoToString<T>(IEnumerable<T> range, string name)
|
|
|
|
|
{
|
|
|
|
|
return $"{name}({range.Count()}) {{{string.Join(", ", range.Select(o => o.ToString()))}}})";
|
|
|
|
|
}
|
2024-01-05 23:49:29 +08:00
|
|
|
|
}
|
2024-01-07 18:52:54 +08:00
|
|
|
|
}
|