70 lines
1.5 KiB
C#
70 lines
1.5 KiB
C#
using System;
|
|
using System.Runtime.CompilerServices;
|
|
using System.Runtime.InteropServices;
|
|
|
|
internal unsafe class FixedArray<T> : IDisposable where T : unmanaged
|
|
{
|
|
private void* _buffer;
|
|
|
|
public int Length { get; private set; }
|
|
|
|
public T this[int i]
|
|
{
|
|
get { return ReadElement(_buffer, i); }
|
|
set { WriteElement(_buffer, i, value); }
|
|
}
|
|
|
|
public unsafe FixedArray(int length, bool clearMemory = false)
|
|
{
|
|
var bufferSize = Marshal.SizeOf<T>() * length;
|
|
_buffer = (void*)Alloc(bufferSize);
|
|
|
|
if (clearMemory)
|
|
{
|
|
Memset(_buffer, 0, bufferSize);
|
|
}
|
|
|
|
Length = length;
|
|
}
|
|
|
|
public ref T ByRef(int i)
|
|
{
|
|
return ref *(T*)((byte*)_buffer + i * sizeof(T));
|
|
}
|
|
|
|
void IDisposable.Dispose()
|
|
{
|
|
Free((IntPtr)_buffer);
|
|
_buffer = null;
|
|
Length = 0;
|
|
}
|
|
|
|
private static T ReadElement(void* buffer, int i)
|
|
{
|
|
return *(T*)((byte*)buffer + i * sizeof(T));
|
|
}
|
|
|
|
private static void WriteElement(void* buffer, int i, T value)
|
|
{
|
|
*(T*)((byte*)buffer + i * sizeof(T)) = value;
|
|
}
|
|
|
|
private unsafe static IntPtr Alloc(int size)
|
|
{
|
|
return Marshal.AllocHGlobal(size);
|
|
}
|
|
|
|
public unsafe static void Free(IntPtr ptr)
|
|
{
|
|
if (ptr != IntPtr.Zero)
|
|
{
|
|
Marshal.FreeHGlobal(ptr);
|
|
}
|
|
}
|
|
|
|
private unsafe static void Memset(void* ptr, byte value, int count)
|
|
{
|
|
Unsafe.InitBlock(ptr, value, (uint)count);
|
|
}
|
|
}
|