DragonECS/src/Internal/ArrayUtility.cs

384 lines
13 KiB
C#
Raw Normal View History

2025-03-14 16:53:25 +08:00
#if DISABLE_DEBUG
#undef DEBUG
#endif
2025-05-17 14:55:31 +08:00
using DCFApixels.DragonECS.Core.Internal;
2025-03-14 16:53:25 +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
{
internal interface ILinkedNext
{
int Next { get; }
}
2025-04-01 19:29:52 +08:00
internal readonly struct LinkedListCountIterator<T> : IEnumerable<T>
where T : ILinkedNext
{
public readonly T[] Array;
public readonly int Count;
public readonly int StartIndex;
2025-04-01 19:29:52 +08:00
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;
}
2024-09-07 17:18:35 +08:00
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;
}
2024-09-07 17:18:35 +08:00
[MethodImpl(MethodImplOptions.AggressiveInlining)]
void IDisposable.Dispose() { }
void IEnumerator.Reset() { throw new NotSupportedException(); }
}
}
2025-04-01 19:29:52 +08:00
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;
}
}
}
2024-09-07 17:18:35 +08:00
2023-04-08 00:47:35 +08:00
internal static class ArrayUtility
{
2025-03-12 13:07:23 +08:00
//TODO потестить
public static void ResizeOrCreate<T>(ref T[] array, int newSize)
{
2025-03-13 20:43:21 +08:00
if (array == null)
2025-03-12 13:07:23 +08:00
{
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;
}
2025-03-19 11:18:25 +08:00
public static int NextPow2(int v)
2024-02-07 22:16:41 +08:00
{
2024-02-13 21:00:01 +08:00
unchecked
{
2025-03-19 11:18:25 +08:00
v--;
v |= v >> 1;
v |= v >> 2;
v |= v >> 4;
v |= v >> 8;
v |= v >> 16;
return ++v;
2024-02-13 21:00:01 +08:00
}
}
2025-03-19 11:18:25 +08:00
public static int NextPow2_ClampOverflow(int v)
2024-02-13 21:00:01 +08:00
{
unchecked
{
2025-03-19 11:18:25 +08:00
const int NO_SIGN_HIBIT = 0x40000000;
if ((v & NO_SIGN_HIBIT) != 0)
2024-02-13 21:00:01 +08:00
{
return int.MaxValue;
}
2025-03-19 11:18:25 +08:00
return NextPow2(v);
2024-02-13 21:00:01 +08:00
}
2024-02-07 22:16:41 +08:00
}
2025-03-19 11:18:25 +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
}
2025-03-24 14:26:40 +08:00
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 UpsizeToNextPow2<T>(ref T[] array, int minSize)
{
if (array == null)
{
minSize = NextPow2(minSize);
array = new T[minSize];
}
else if (minSize > array.Length)
{
minSize = NextPow2(minSize);
Array.Resize(ref array, minSize);
}
}
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
{
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
{
2024-11-26 02:40:59 +08:00
//Console.WriteLine($"{typeof(T).Name} - {Marshal.SizeOf<T>()} - {capacity} - {Marshal.SizeOf<T>() * capacity}");
2025-05-17 14:55:31 +08:00
//return (T*)Marshal.AllocHGlobal(Marshal.SizeOf<T>() * capacity).ToPointer();
return MemoryAllocator.Alloc<T>(capacity).As<T>();
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
{
2025-05-17 14:55:31 +08:00
//ptr = (T*)Marshal.AllocHGlobal(Marshal.SizeOf<T>() * capacity).ToPointer();
ptr = MemoryAllocator.Alloc<T>(capacity).As<T>();
2024-01-07 18:52:54 +08:00
}
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
{
2025-05-17 14:55:31 +08:00
//int newSize = MetaCache<T>.Size * capacity;
//byte* newPointer = (byte*)Marshal.AllocHGlobal(newSize).ToPointer();
//
//for (int i = 0; i < newSize; i++)
//{
// *(newPointer + i) = 0;
//}
//
//return (T*)newPointer;
return MemoryAllocator.AllocAndInit<T>(capacity).As<T>();
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
{
2025-05-17 14:55:31 +08:00
//int newSize = MetaCache<T>.Size * capacity;
//byte* newPointer = (byte*)Marshal.AllocHGlobal(newSize).ToPointer();
//
//for (int i = 0; i < newSize; i++)
//{
// *(newPointer + i) = 0;
//}
//
//ptr = (T*)newPointer;
ptr = MemoryAllocator.AllocAndInit<T>(capacity).As<T>();
2024-01-07 18:52:54 +08:00
}
2023-12-24 18:11:20 +08:00
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Free(void* pointer)
{
2025-05-17 14:55:31 +08:00
//Marshal.FreeHGlobal(new IntPtr(pointer));
MemoryAllocator.Free(dataPtr: pointer);
2023-12-24 18:11:20 +08:00
}
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
{
2025-05-17 14:55:31 +08:00
//Marshal.FreeHGlobal(new IntPtr(pointer));
MemoryAllocator.Free(dataPtr: pointer);
2024-01-07 18:52:54 +08:00
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
{
2025-05-17 14:55:31 +08:00
//return (T*)(Marshal.ReAllocHGlobal(
// new IntPtr(oldPointer),
// new IntPtr(MetaCache<T>.Size * newCount))).ToPointer();
return MemoryAllocator.Realloc<T>(MemoryAllocator.Handler.FromDataPtr(oldPointer), newCount).As<T>();
2023-12-24 18:11:20 +08:00
}
2024-11-25 10:30:23 +08:00
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static T* ResizeAndInit<T>(void* oldPointer, int oldSize, int newSize) where T : unmanaged
{
2025-05-17 14:55:31 +08:00
//int sizeT = MetaCache<T>.Size;
//T* result = (T*)Marshal.ReAllocHGlobal(
// new IntPtr(oldPointer),
// new IntPtr(sizeT * newSize)).ToPointer();
//Init((byte*)result, sizeT * oldSize, sizeT * newSize);
//return result;
return MemoryAllocator.ReallocAndInit<T>(MemoryAllocator.Handler.FromDataPtr(oldPointer), oldSize, newSize).As<T>();
2024-11-25 10:30:23 +08:00
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static void Init(byte* pointer, int startByteIndex, int endByteIndex)
{
for (int i = startByteIndex; i < endByteIndex; i++)
{
*(pointer + i) = 0;
}
}
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
}