DragonECS/src/Utils/ArrayUtility.cs

185 lines
6.1 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 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)
{
return 1 << (GetHighBitNumber((uint)minSize - 1u) + 1);
}
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;
}
public static EnumerableInt Range(int start, int length) => new EnumerableInt(start, length);
public static EnumerableInt StartEnd(int start, int end) => new EnumerableInt(start, end - start);
IEnumerator<int> IEnumerable<int>.GetEnumerator() => GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Enumerator GetEnumerator() => 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 => _current;
}
object IEnumerator.Current => Current;
2023-12-24 18:11:20 +08:00
2024-01-07 18:52:54 +08:00
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool MoveNext() => ++_current < _max;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Reset() { }
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Dispose() { }
}
}
2023-12-24 18:11:20 +08:00
internal static unsafe class UnmanagedArrayUtility
{
[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 = Marshal.SizeOf(typeof(T)) * capacity;
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
{
int newSize = Marshal.SizeOf(typeof(T)) * capacity;
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),
new IntPtr(Marshal.SizeOf(typeof(T)) * newCount))).ToPointer();
}
}
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
}