DragonECS/src/Internal/ArrayUtility.cs

270 lines
8.8 KiB
C#
Raw Normal View History

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
{
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]; }
}
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-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
{
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
{
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++)
2024-11-17 21:43:50 +08:00
{
2023-12-24 18:11:20 +08:00
*(newPointer + i) = 0;
2024-11-17 21:43:50 +08:00
}
2023-12-24 18:11:20 +08:00
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
{
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++)
2024-11-17 21:43:50 +08:00
{
2024-01-07 18:52:54 +08:00
*(newPointer + i) = 0;
2024-11-17 21:43:50 +08:00
}
2024-01-07 18:52:54 +08:00
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),
new IntPtr(MetaCache<T>.Size * newCount))).ToPointer();
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
}