From edfc92dad2e16625fb602f5a6460bbf16e72c718 Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Fri, 19 Jun 2020 12:22:01 +0200 Subject: [PATCH] Added [ReadOnly]Memory2D.DangerousCreate --- .../Memory/Internals/ThrowHelper.cs | 8 +++ .../Memory/Memory2D{T}.cs | 51 ++++++++++++++++--- .../Memory/ReadOnlyMemory2D{T}.cs | 51 ++++++++++++++++--- 3 files changed, 96 insertions(+), 14 deletions(-) diff --git a/Microsoft.Toolkit.HighPerformance/Memory/Internals/ThrowHelper.cs b/Microsoft.Toolkit.HighPerformance/Memory/Internals/ThrowHelper.cs index 123f131a..70b5f201 100644 --- a/Microsoft.Toolkit.HighPerformance/Memory/Internals/ThrowHelper.cs +++ b/Microsoft.Toolkit.HighPerformance/Memory/Internals/ThrowHelper.cs @@ -37,6 +37,14 @@ namespace Microsoft.Toolkit.HighPerformance.Memory.Internals throw new ArrayTypeMismatchException("The given array doesn't match the specified type "); } + /// + /// Throws an when using an array of an invalid type. + /// + public static void ThrowArgumentExceptionForUnsupportedType() + { + throw new ArgumentException("The specified object type is not supported"); + } + /// /// Throws an when the a given coordinate is invalid. /// diff --git a/Microsoft.Toolkit.HighPerformance/Memory/Memory2D{T}.cs b/Microsoft.Toolkit.HighPerformance/Memory/Memory2D{T}.cs index 39e8933b..59758764 100644 --- a/Microsoft.Toolkit.HighPerformance/Memory/Memory2D{T}.cs +++ b/Microsoft.Toolkit.HighPerformance/Memory/Memory2D{T}.cs @@ -60,7 +60,6 @@ namespace Microsoft.Toolkit.HighPerformance.Memory /// Thrown when either or are invalid. /// /// The total area must match the lenght of . - [MethodImpl(MethodImplOptions.AggressiveInlining)] public Memory2D(T[] array, int height, int width) : this(array, 0, height, width, 0) { @@ -83,7 +82,6 @@ namespace Microsoft.Toolkit.HighPerformance.Memory /// /// Thrown when the requested area is outside of bounds for . /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] public Memory2D(T[] array, int offset, int height, int width, int pitch) { if (array.IsCovariant()) @@ -224,7 +222,6 @@ namespace Microsoft.Toolkit.HighPerformance.Memory /// Thrown when doesn't match . /// /// Thrown when a parameter is invalid. - [MethodImpl(MethodImplOptions.AggressiveInlining)] public Memory2D(T[,,] array, int depth) { if (array.IsCovariant()) @@ -257,7 +254,6 @@ namespace Microsoft.Toolkit.HighPerformance.Memory /// Thrown when doesn't match . /// /// Thrown when a parameter is invalid. - [MethodImpl(MethodImplOptions.AggressiveInlining)] public Memory2D(T[,,] array, int depth, int row, int column, int height, int width) { if (array.IsCovariant()) @@ -312,7 +308,6 @@ namespace Microsoft.Toolkit.HighPerformance.Memory /// Thrown when either or are invalid. /// /// The total area must match the lenght of . - [MethodImpl(MethodImplOptions.AggressiveInlining)] public Memory2D(Memory memory, int height, int width) : this(memory, 0, height, width, 0) { @@ -332,7 +327,6 @@ namespace Microsoft.Toolkit.HighPerformance.Memory /// /// Thrown when the requested area is outside of bounds for . /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] public Memory2D(Memory memory, int offset, int height, int width, int pitch) { if ((uint)offset > (uint)memory.Length) @@ -397,6 +391,50 @@ namespace Microsoft.Toolkit.HighPerformance.Memory this.pitch = pitch; } + /// + /// Creates a new instance from an arbitrary object. + /// + /// The instance holding the data to map. + /// The target reference to point to (it must be within ). + /// The height of the 2D memory area to map. + /// The width of the 2D memory area to map. + /// The pitch of the 2D memory area to map. + /// A instaance with the specified parameters. + /// The parameter is not validated, and it's responsability of the caller to ensure it's valid. + /// + /// Thrown when is of an unsupported type. + /// + /// + /// Thrown when one of the input parameters is out of range. + /// + [Pure] + public static Memory2D DangerousCreate(object instance, ref T value, int height, int width, int pitch) + { + if (instance.GetType() == typeof(Memory)) + { + ThrowHelper.ThrowArgumentExceptionForUnsupportedType(); + } + + if (height < 0) + { + ThrowHelper.ThrowArgumentOutOfRangeExceptionForHeight(); + } + + if (width < 0) + { + ThrowHelper.ThrowArgumentOutOfRangeExceptionForWidth(); + } + + if (pitch < 0) + { + ThrowHelper.ThrowArgumentOutOfRangeExceptionForPitch(); + } + + IntPtr offset = instance.DangerousGetObjectDataByteOffset(ref value); + + return new Memory2D(instance, offset, height, width, pitch); + } + /// /// Gets an empty instance. /// @@ -460,7 +498,6 @@ namespace Microsoft.Toolkit.HighPerformance.Memory } else { - // The only other possible cases is with the instance being an array ref T r0 = ref this.instance.DangerousGetObjectDataReferenceAt(this.offset); return new Span2D(ref r0, this.height, this.width, this.pitch); diff --git a/Microsoft.Toolkit.HighPerformance/Memory/ReadOnlyMemory2D{T}.cs b/Microsoft.Toolkit.HighPerformance/Memory/ReadOnlyMemory2D{T}.cs index 1c2deb84..cd3dcb0e 100644 --- a/Microsoft.Toolkit.HighPerformance/Memory/ReadOnlyMemory2D{T}.cs +++ b/Microsoft.Toolkit.HighPerformance/Memory/ReadOnlyMemory2D{T}.cs @@ -57,7 +57,6 @@ namespace Microsoft.Toolkit.HighPerformance.Memory /// Thrown when either or are invalid. /// /// The total area must match the lenght of . - [MethodImpl(MethodImplOptions.AggressiveInlining)] public ReadOnlyMemory2D(T[] array, int height, int width) : this(array, 0, height, width, 0) { @@ -80,7 +79,6 @@ namespace Microsoft.Toolkit.HighPerformance.Memory /// /// Thrown when the requested area is outside of bounds for . /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] public ReadOnlyMemory2D(T[] array, int offset, int height, int width, int pitch) { if (array.IsCovariant()) @@ -221,7 +219,6 @@ namespace Microsoft.Toolkit.HighPerformance.Memory /// Thrown when doesn't match . /// /// Thrown when a parameter is invalid. - [MethodImpl(MethodImplOptions.AggressiveInlining)] public ReadOnlyMemory2D(T[,,] array, int depth) { if (array.IsCovariant()) @@ -254,7 +251,6 @@ namespace Microsoft.Toolkit.HighPerformance.Memory /// Thrown when doesn't match . /// /// Thrown when a parameter is invalid. - [MethodImpl(MethodImplOptions.AggressiveInlining)] public ReadOnlyMemory2D(T[,,] array, int depth, int row, int column, int height, int width) { if (array.IsCovariant()) @@ -309,7 +305,6 @@ namespace Microsoft.Toolkit.HighPerformance.Memory /// Thrown when either or are invalid. /// /// The total area must match the lenght of . - [MethodImpl(MethodImplOptions.AggressiveInlining)] public ReadOnlyMemory2D(ReadOnlyMemory memory, int height, int width) : this(memory, 0, height, width, 0) { @@ -329,7 +324,6 @@ namespace Microsoft.Toolkit.HighPerformance.Memory /// /// Thrown when the requested area is outside of bounds for . /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] public ReadOnlyMemory2D(ReadOnlyMemory memory, int offset, int height, int width, int pitch) { if ((uint)offset > (uint)memory.Length) @@ -394,6 +388,50 @@ namespace Microsoft.Toolkit.HighPerformance.Memory this.pitch = pitch; } + /// + /// Creates a new instance from an arbitrary object. + /// + /// The instance holding the data to map. + /// The target reference to point to (it must be within ). + /// The height of the 2D memory area to map. + /// The width of the 2D memory area to map. + /// The pitch of the 2D memory area to map. + /// A instaance with the specified parameters. + /// The parameter is not validated, and it's responsability of the caller to ensure it's valid. + /// + /// Thrown when is of an unsupported type. + /// + /// + /// Thrown when one of the input parameters is out of range. + /// + [Pure] + public static ReadOnlyMemory2D DangerousCreate(object instance, ref T value, int height, int width, int pitch) + { + if (instance.GetType() == typeof(ReadOnlyMemory)) + { + ThrowHelper.ThrowArgumentExceptionForUnsupportedType(); + } + + if (height < 0) + { + ThrowHelper.ThrowArgumentOutOfRangeExceptionForHeight(); + } + + if (width < 0) + { + ThrowHelper.ThrowArgumentOutOfRangeExceptionForWidth(); + } + + if (pitch < 0) + { + ThrowHelper.ThrowArgumentOutOfRangeExceptionForPitch(); + } + + IntPtr offset = instance.DangerousGetObjectDataByteOffset(ref value); + + return new ReadOnlyMemory2D(instance, offset, height, width, pitch); + } + /// /// Gets an empty instance. /// @@ -457,7 +495,6 @@ namespace Microsoft.Toolkit.HighPerformance.Memory } else { - // The only other possible cases is with the instance being an array ref T r0 = ref this.instance.DangerousGetObjectDataReferenceAt(this.offset); return new ReadOnlySpan2D(r0, this.height, this.width, this.pitch);