Added new namespace `Misaki.HighPerformance.Image` for image processing, including classes for animated GIF handling and memory management. Added `AnimatedFrameResult` class for individual frames in animated images. Added `AnimatedGifEnumerator` class for enumerating frames in animated GIFs. Added `ColorComponents` enum for different color formats. Added `ImageInfo` struct for image dimensions and color components. Added `CRuntime` class for low-level memory management functions. Added `MemoryStats` class to track memory allocation statistics. Added utility functions for creating multi-dimensional arrays. Added new structures for fixed-size UTF-8 encoded strings. Added benchmarking classes to test new memory management features. Changed `StbImage.cs` to include new namespaces and functionality for image data manipulation. Changed project files to target .NET 9.0 and enable new features. Changed `Arena.cs` and `DynamicArena.cs` to use `nuint` for size parameters. Changed `BitSet.cs` to enhance bit manipulation methods. Changed `Program.cs` to run `FunctionPtrBenchmark` for performance testing. Removed memory tracking code from `AllocationManager.cs`, including the `_allocated` dictionary and related logic. Removed `Free` method from `IAllocator.cs` interface. Removed `UNSAFE_COLLECTION_CHECK` preprocessor directive from the codebase. Refactored various files to improve organization, moving from `Unsafe` to `LowLevel` namespace. Refactored `MemoryUtilities` class to include new memory operation methods. Refactored `UnsafeUtilities.cs` to support new collection structures.
138 lines
6.8 KiB
C#
138 lines
6.8 KiB
C#
using Misaki.HighPerformance.LowLevel.Collections;
|
|
using Misaki.HighPerformance.LowLevel.Collections.Contracts;
|
|
using System.Runtime.InteropServices;
|
|
|
|
namespace Misaki.HighPerformance.LowLevel.Helpers;
|
|
|
|
/// <summary>
|
|
/// Provides extension methods for copying elements between unsafe collections and spans, converting collections to
|
|
/// arrays or lists, and searching for values.
|
|
/// </summary>
|
|
public unsafe static class UnsafeCollectionExtensions
|
|
{
|
|
/// <summary>
|
|
/// Copies elements from a source UnsafeCollection to a destination Span, ensuring both have the same size.
|
|
/// </summary>
|
|
/// <typeparam name="T">Specifies the type of elements being copied, which must be unmanaged.</typeparam>
|
|
/// <param name="source">Represents the source collection from which elements are copied.</param>
|
|
/// <param name="destination">Represents the target span where elements are copied to.</param>
|
|
/// <exception cref="ArgumentException">Thrown when the sizes of the source collection and destination span do not match.</exception>
|
|
public static void CopyTo<T>(this IUnsafeCollection<T> source, Span<T> destination)
|
|
where T : unmanaged
|
|
{
|
|
if (source.Count > destination.Length)
|
|
{
|
|
throw new ArgumentException("Source collection is larger than the destination span.");
|
|
}
|
|
|
|
fixed (T* ptr = destination)
|
|
{
|
|
SystemUnsfae.CopyBlock(ptr, source.GetUnsafePtr(), (uint)(source.Count * sizeof(T)));
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Copies a range of elements from a source collection to a destination span, ensuring both are adequately sized.
|
|
/// </summary>
|
|
/// <typeparam name="T">Specifies the type of elements being copied, which must be a value type.</typeparam>
|
|
/// <param name="source">The collection from which elements are copied.</param>
|
|
/// <param name="destination">The span where the elements will be copied to.</param>
|
|
/// <param name="sourceIndex">The starting index in the source collection for the copy operation.</param>
|
|
/// <param name="destinationIndex">The starting index in the destination span where the elements will be placed.</param>
|
|
/// <param name="length">The number of elements to copy from the source to the destination.</param>
|
|
/// <exception cref="ArgumentException">Thrown when the specified range exceeds the bounds of the source collection or destination span.</exception>
|
|
public static void CopyTo<T>(this IUnsafeCollection<T> source, Span<T> destination, int sourceIndex, int destinationIndex, int length)
|
|
where T : unmanaged
|
|
{
|
|
if (sourceIndex + length > source.Count || destinationIndex + length > destination.Length)
|
|
{
|
|
throw new ArgumentException("Source collection or destination span is too small for the specified range.");
|
|
}
|
|
|
|
fixed (T* ptr = destination)
|
|
{
|
|
SystemUnsfae.CopyBlock(ptr + destinationIndex, (byte*)source.GetUnsafePtr() + sourceIndex * sizeof(T), (uint)(length * sizeof(T)));
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Copies elements from a source span to a destination unsafe collection, ensuring both have the same size.
|
|
/// </summary>
|
|
/// <typeparam name="T">Specifies the type of elements being copied, which must be unmanaged.</typeparam>
|
|
/// <param name="destination">Represents the unsafe collection that will receive the copied elements.</param>
|
|
/// <param name="source">Represents the span containing the elements to be copied to the unsafe collection.</param>
|
|
/// <exception cref="ArgumentException">Thrown when the source span and destination collection have different sizes.</exception>
|
|
public static void CopyFrom<T>(this IUnsafeCollection<T> destination, Span<T> source)
|
|
where T : unmanaged
|
|
{
|
|
if (destination.Count > source.Length)
|
|
{
|
|
throw new ArgumentException("Destination collection is larger than the source span.");
|
|
}
|
|
|
|
fixed (T* ptr = source)
|
|
{
|
|
SystemUnsfae.CopyBlock(destination.GetUnsafePtr(), ptr, (uint)(source.Length * sizeof(T)));
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Copies a specified range of elements from a source span to a destination collection.
|
|
/// </summary>
|
|
/// <typeparam name="T">Represents the type of elements being copied, which must be unmanaged.</typeparam>
|
|
/// <param name="destination">The collection where elements will be copied to.</param>
|
|
/// <param name="source">The span containing the elements to be copied.</param>
|
|
/// <param name="sourceIndex">The starting index in the source span from which to begin copying.</param>
|
|
/// <param name="destinationIndex">The starting index in the destination collection where the elements will be placed.</param>
|
|
/// <param name="length">The number of elements to copy from the source span to the destination collection.</param>
|
|
/// <exception cref="ArgumentException">Thrown when the specified range exceeds the bounds of the source span or destination collection.</exception>
|
|
public static void CopyFrom<T>(this IUnsafeCollection<T> destination, Span<T> source, int sourceIndex, int destinationIndex, int length)
|
|
where T : unmanaged
|
|
{
|
|
if (sourceIndex + length > source.Length || destinationIndex + length > destination.Count)
|
|
{
|
|
throw new ArgumentException("Source span or destination collection is too small for the specified range.");
|
|
}
|
|
|
|
fixed (T* ptr = source)
|
|
{
|
|
SystemUnsfae.CopyBlock((byte*)destination.GetUnsafePtr() + destinationIndex * sizeof(T), ptr + sourceIndex, (uint)(length * sizeof(T)));
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Converts an UnsafeCollection into a Span for efficient memory access.
|
|
/// </summary>
|
|
/// <typeparam name="T">Represents a type that can be stored in unmanaged memory.</typeparam>
|
|
/// <param name="source">The UnsafeCollection instance to be converted into a Span.</param>
|
|
/// <returns>A Span that provides a view over the elements of the UnsafeCollection.</returns>
|
|
public static Span<T> AsSpan<T>(this IUnsafeCollection<T> source)
|
|
where T : unmanaged
|
|
{
|
|
return new(source.GetUnsafePtr(), source.Count);
|
|
}
|
|
|
|
public static UnsafeArray<T> ToUnsafeArray<T>(this T[] source, Allocator allocator)
|
|
where T : unmanaged
|
|
{
|
|
var array = new UnsafeArray<T>(source.Length, allocator);
|
|
fixed (T* ptr = source)
|
|
{
|
|
MemCpy(array.GetUnsafePtr(), ptr, (uint)(source.Length * sizeof(T)));
|
|
}
|
|
|
|
return array;
|
|
}
|
|
|
|
public static UnsafeList<T> ToUnsafeList<T>(this List<T> source, Allocator allocator)
|
|
where T : unmanaged
|
|
{
|
|
var list = new UnsafeList<T>(source.Count, allocator);
|
|
fixed (T* ptr = CollectionsMarshal.AsSpan(source))
|
|
{
|
|
MemCpy(list.GetUnsafePtr(), ptr, (uint)(source.Count * sizeof(T)));
|
|
}
|
|
|
|
return list;
|
|
}
|
|
} |