using Misaki.HighPerformance.LowLevel.Buffer;
using Misaki.HighPerformance.LowLevel.Collections;
using System.Diagnostics;
using System.Runtime.InteropServices;
namespace Misaki.HighPerformance.LowLevel.Utilities;
///
/// Provides extension methods for copying elements between unsafe collections and spans, converting collections to
/// arrays or lists, and searching for values.
///
public static unsafe class UnsafeCollectionUtility
{
[Conditional("DEBUG")]
internal static void ReportDoubleFree(void* buffer)
{
if (buffer == null)
{
return;
}
var message = $"The {typeof(T).Name} is not created or already disposed.";
#if MHP_ENABLE_STACKTRACE
var stackTrace = new StackTrace(1, true);
var sb = new System.Text.StringBuilder();
foreach (var frame in stackTrace.GetFrames())
{
var fileName = frame?.GetFileName();
if (frame != null)
{
var methodInfo = DiagnosticMethodInfo.Create(frame);
sb.AppendLine($"File: {fileName}, Type: {methodInfo?.DeclaringTypeName}, Method: {methodInfo?.Name}, Line: {frame.GetFileLineNumber()}");
}
}
message += Environment.NewLine + sb.ToString();
#endif
Debug.WriteLine(message);
}
///
/// Converts a managed array to an UnsafeArray by copying its elements to unmanaged memory.
///
/// The type of elements in the array, which must be unmanaged.
/// The managed array to convert.
/// The allocation handle to use for memory allocation of the UnsafeArray.
/// A new UnsafeArray containing a copy of the source array elements.
public static UnsafeArray ToUnsafeArray(this T[] source, AllocationHandle allocationHandle)
where T : unmanaged
{
var array = new UnsafeArray(source.Length, allocationHandle);
fixed (T* pSrc = source)
{
MemCpy(array.GetUnsafePtr(), pSrc, (uint)(source.Length * sizeof(T)));
}
return array;
}
///
/// Converts a managed List to an UnsafeList by copying its elements to unmanaged memory.
///
/// The type of elements in the list, which must be unmanaged.
/// The managed List to convert.
/// The allocation handle to use for memory allocation of the UnsafeList.
/// A new UnsafeList containing a copy of the source list elements.
public static UnsafeList ToUnsafeList(this List source, AllocationHandle allocationHandle)
where T : unmanaged
{
var list = new UnsafeList(source.Count, allocationHandle);
fixed (T* pSrc = CollectionsMarshal.AsSpan(source))
{
MemCpy(list.GetUnsafePtr(), pSrc, (uint)(source.Count * sizeof(T)));
}
return list;
}
}