public void Test_DangerousGetObjectDataByteOffset() { var a = new TestClass { Number = 42, Character = 'a', Text = "Hello" }; IntPtr ptr = ObjectMarshal.DangerousGetObjectDataByteOffset(a, ref a.Number); ref int number = ref ObjectMarshal.DangerousGetObjectDataReferenceAt<int>(a, ptr);
public static unsafe IntPtr GetObjectDataOrReferenceByteOffset <T>(object?obj, ref T data) { if (obj is null) { return((IntPtr)Unsafe.AsPointer(ref data)); } return(ObjectMarshal.DangerousGetObjectDataByteOffset(obj, ref data)); }
/// <summary> /// Initializes a new instance of the <see cref="Span2D{T}"/> struct wrapping a 2D array. /// </summary> /// <param name="array">The given 2D array to wrap.</param> /// <param name="row">The target row to map within <paramref name="array"/>.</param> /// <param name="column">The target column to map within <paramref name="array"/>.</param> /// <param name="height">The height to map within <paramref name="array"/>.</param> /// <param name="width">The width to map within <paramref name="array"/>.</param> /// <exception cref="ArrayTypeMismatchException"> /// Thrown when <paramref name="array"/> doesn't match <typeparamref name="T"/>. /// </exception> /// <exception cref="ArgumentOutOfRangeException"> /// Thrown when either <paramref name="height"/>, <paramref name="width"/> or <paramref name="height"/> /// are negative or not within the bounds that are valid for <paramref name="array"/>. /// </exception> public Span2D(T[, ]?array, int row, int column, int height, int width) { if (array is null) { if (row != 0 || column != 0 || height != 0 || width != 0) { ThrowHelper.ThrowArgumentException(); } this = default; return; } if (array.IsCovariant()) { ThrowHelper.ThrowArrayTypeMismatchException(); } int rows = array.GetLength(0), columns = array.GetLength(1); if ((uint)row >= (uint)rows) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForRow(); } if ((uint)column >= (uint)columns) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForColumn(); } if ((uint)height > (uint)(rows - row)) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForHeight(); } if ((uint)width > (uint)(columns - column)) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForWidth(); } #if SPAN_RUNTIME_SUPPORT this.span = MemoryMarshal.CreateSpan(ref array.DangerousGetReferenceAt(row, column), height); #else this.Instance = array; this.Offset = ObjectMarshal.DangerousGetObjectDataByteOffset(array, ref array.DangerousGetReferenceAt(row, column)); this.height = height; #endif this.width = width; this.Stride = columns; }
/// <summary> /// Initializes a new instance of the <see cref="ReadOnlyMemory2D{T}"/> struct wrapping a layer in a 3D array. /// </summary> /// <param name="array">The given 3D array to wrap.</param> /// <param name="depth">The target layer to map within <paramref name="array"/>.</param> /// <exception cref="ArgumentOutOfRangeException">Thrown when a parameter is invalid.</exception> public ReadOnlyMemory2D(T[,,] array, int depth) { if ((uint)depth >= (uint)array.GetLength(0)) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForDepth(); } this.instance = array; this.offset = ObjectMarshal.DangerousGetObjectDataByteOffset(array, ref array.DangerousGetReferenceAt(depth, 0, 0)); this.height = array.GetLength(1); this.width = array.GetLength(2); this.pitch = 0; }
/// <summary> /// Initializes a new instance of the <see cref="Memory2D{T}"/> struct. /// </summary> /// <param name="memory">The target <see cref="Memory{T}"/> to wrap.</param> /// <param name="offset">The initial offset within <paramref name="memory"/>.</param> /// <param name="height">The height of the resulting 2D area.</param> /// <param name="width">The width of each row in the resulting 2D area.</param> /// <param name="pitch">The pitch in the resulting 2D area.</param> /// <exception cref="ArgumentOutOfRangeException"> /// Thrown when one of the input parameters is out of range. /// </exception> /// <exception cref="ArgumentException"> /// Thrown when the requested area is outside of bounds for <paramref name="memory"/>. /// </exception> internal Memory2D(Memory <T> memory, int offset, int height, int width, int pitch) { if ((uint)offset > (uint)memory.Length) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForOffset(); } if (height < 0) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForHeight(); } if (width < 0) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForWidth(); } if (pitch < 0) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForPitch(); } if (width == 0 || height == 0) { this = default; return; } int area = OverflowHelper.ComputeInt32Area(height, width, pitch), remaining = memory.Length - offset; if (area > remaining) { ThrowHelper.ThrowArgumentException(); } // Check if the Memory<T> instance wraps a string. This is possible in case // consumers do an unsafe cast for the entire Memory<T> object, and while not // really safe it is still supported in CoreCLR too, so we're following suit here. if (typeof(T) == typeof(char) && MemoryMarshal.TryGetString(Unsafe.As <Memory <T>, Memory <char> >(ref memory), out string?text, out int textStart, out _)) { ref char r0 = ref text.DangerousGetReferenceAt(textStart + offset); this.instance = text; this.offset = ObjectMarshal.DangerousGetObjectDataByteOffset(text, ref r0); }
/// <summary> /// Initializes a new instance of the <see cref="Memory2D{T}"/> struct wrapping a 2D array. /// </summary> /// <param name="array">The given 2D array to wrap.</param> /// <param name="row">The target row to map within <paramref name="array"/>.</param> /// <param name="column">The target column to map within <paramref name="array"/>.</param> /// <param name="height">The height to map within <paramref name="array"/>.</param> /// <param name="width">The width to map within <paramref name="array"/>.</param> /// <exception cref="ArrayTypeMismatchException"> /// Thrown when <paramref name="array"/> doesn't match <typeparamref name="T"/>. /// </exception> /// <exception cref="ArgumentOutOfRangeException"> /// Thrown when either <paramref name="height"/>, <paramref name="width"/> or <paramref name="height"/> /// are negative or not within the bounds that are valid for <paramref name="array"/>. /// </exception> public Memory2D(T[, ]?array, int row, int column, int height, int width) { if (array is null) { if (row != 0 || column != 0 || height != 0 || width != 0) { ThrowHelper.ThrowArgumentException(); } this = default; return; } if (array.IsCovariant()) { ThrowHelper.ThrowArrayTypeMismatchException(); } int rows = array.GetLength(0), columns = array.GetLength(1); if ((uint)row >= (uint)rows) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForRow(); } if ((uint)column >= (uint)columns) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForColumn(); } if ((uint)height > (uint)(rows - row)) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForHeight(); } if ((uint)width > (uint)(columns - column)) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForWidth(); } this.instance = array; this.offset = ObjectMarshal.DangerousGetObjectDataByteOffset(array, ref array.DangerousGetReferenceAt(row, column)); this.height = height; this.width = width; this.pitch = columns - width; }
/// <summary> /// Initializes a new instance of the <see cref="ReadOnlyMemory2D{T}"/> struct. /// </summary> /// <param name="memory">The target <see cref="ReadOnlyMemory{T}"/> to wrap.</param> /// <param name="offset">The initial offset within <paramref name="memory"/>.</param> /// <param name="height">The height of the resulting 2D area.</param> /// <param name="width">The width of each row in the resulting 2D area.</param> /// <param name="pitch">The pitch in the resulting 2D area.</param> /// <exception cref="ArgumentOutOfRangeException"> /// Thrown when one of the input parameters is out of range. /// </exception> /// <exception cref="ArgumentException"> /// Thrown when the requested area is outside of bounds for <paramref name="memory"/>. /// </exception> internal ReadOnlyMemory2D(ReadOnlyMemory <T> memory, int offset, int height, int width, int pitch) { if ((uint)offset > (uint)memory.Length) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForOffset(); } if (height < 0) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForHeight(); } if (width < 0) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForWidth(); } if (pitch < 0) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForPitch(); } if (width == 0 || height == 0) { this = default; return; } int area = OverflowHelper.ComputeInt32Area(height, width, pitch), remaining = memory.Length - offset; if (area > remaining) { ThrowHelper.ThrowArgumentException(); } // Check the supported underlying objects, like in Memory2D<T> if (typeof(T) == typeof(char) && MemoryMarshal.TryGetString(Unsafe.As <ReadOnlyMemory <T>, ReadOnlyMemory <char> >(ref memory), out string?text, out int textStart, out _)) { ref char r0 = ref text.DangerousGetReferenceAt(textStart + offset); this.instance = text; this.offset = ObjectMarshal.DangerousGetObjectDataByteOffset(text, ref r0); }
/// <summary> /// Initializes a new instance of the <see cref="Span2D{T}"/> struct. /// </summary> /// <param name="array">The target array to wrap.</param> /// <param name="offset">The initial offset within <paramref name="array"/>.</param> /// <param name="height">The height of the resulting 2D area.</param> /// <param name="width">The width of each row in the resulting 2D area.</param> /// <param name="pitch">The pitch in the resulting 2D area.</param> /// <exception cref="ArrayTypeMismatchException"> /// Thrown when <paramref name="array"/> doesn't match <typeparamref name="T"/>. /// </exception> /// <exception cref="ArgumentOutOfRangeException"> /// Thrown when one of the input parameters is out of range. /// </exception> /// <exception cref="ArgumentException"> /// Thrown when the requested area is outside of bounds for <paramref name="array"/>. /// </exception> public Span2D(T[] array, int offset, int height, int width, int pitch) { if (array.IsCovariant()) { ThrowHelper.ThrowArrayTypeMismatchException(); } if ((uint)offset > (uint)array.Length) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForOffset(); } if (height < 0) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForHeight(); } if (width < 0) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForWidth(); } if (pitch < 0) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForPitch(); } int area = OverflowHelper.ComputeInt32Area(height, width, pitch), remaining = array.Length - offset; if (area > remaining) { ThrowHelper.ThrowArgumentException(); } #if SPAN_RUNTIME_SUPPORT this.span = MemoryMarshal.CreateSpan(ref array.DangerousGetReferenceAt(offset), height); #else this.Instance = array; this.Offset = ObjectMarshal.DangerousGetObjectDataByteOffset(array, ref array.DangerousGetReferenceAt(offset)); this.height = height; #endif this.width = width; this.Stride = width + pitch; }
/// <summary> /// Initializes a new instance of the <see cref="Memory2D{T}"/> struct. /// </summary> /// <param name="array">The target array to wrap.</param> /// <param name="offset">The initial offset within <paramref name="array"/>.</param> /// <param name="height">The height of the resulting 2D area.</param> /// <param name="width">The width of each row in the resulting 2D area.</param> /// <param name="pitch">The pitch in the resulting 2D area.</param> /// <exception cref="ArrayTypeMismatchException"> /// Thrown when <paramref name="array"/> doesn't match <typeparamref name="T"/>. /// </exception> /// <exception cref="ArgumentOutOfRangeException"> /// Thrown when one of the input parameters is out of range. /// </exception> /// <exception cref="ArgumentException"> /// Thrown when the requested area is outside of bounds for <paramref name="array"/>. /// </exception> public Memory2D(T[] array, int offset, int height, int width, int pitch) { if (array.IsCovariant()) { ThrowHelper.ThrowArrayTypeMismatchException(); } if ((uint)offset > (uint)array.Length) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForOffset(); } if (height < 0) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForHeight(); } if (width < 0) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForWidth(); } if (pitch < 0) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForPitch(); } int area = OverflowHelper.ComputeInt32Area(height, width, pitch), remaining = array.Length - offset; if (area > remaining) { ThrowHelper.ThrowArgumentException(); } this.instance = array; this.offset = ObjectMarshal.DangerousGetObjectDataByteOffset(array, ref array.DangerousGetReferenceAt(offset)); this.height = height; this.width = width; this.pitch = pitch; }
/// <summary> /// Initializes a new instance of the <see cref="Span2D{T}"/> struct wrapping a layer in a 3D array. /// </summary> /// <param name="array">The given 3D array to wrap.</param> /// <param name="depth">The target layer to map within <paramref name="array"/>.</param> /// <exception cref="ArrayTypeMismatchException"> /// Thrown when <paramref name="array"/> doesn't match <typeparamref name="T"/>. /// </exception> /// <exception cref="ArgumentOutOfRangeException">Thrown when a parameter is invalid.</exception> public Span2D(T[,,] array, int depth) { if (array.IsCovariant()) { ThrowHelper.ThrowArrayTypeMismatchException(); } if ((uint)depth >= (uint)array.GetLength(0)) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForDepth(); } #if SPAN_RUNTIME_SUPPORT this.span = MemoryMarshal.CreateSpan(ref array.DangerousGetReferenceAt(depth, 0, 0), array.GetLength(1)); #else this.Instance = array; this.Offset = ObjectMarshal.DangerousGetObjectDataByteOffset(array, ref array.DangerousGetReferenceAt(depth, 0, 0)); this.height = array.GetLength(1); #endif this.width = this.Stride = array.GetLength(2); }
/// <summary> /// Initializes a new instance of the <see cref="Span2D{T}"/> struct wrapping a 2D array. /// </summary> /// <param name="array">The given 2D array to wrap.</param> /// <exception cref="ArrayTypeMismatchException"> /// Thrown when <paramref name="array"/> doesn't match <typeparamref name="T"/>. /// </exception> public Span2D(T[, ]?array) { if (array is null) { this = default; return; } if (array.IsCovariant()) { ThrowHelper.ThrowArrayTypeMismatchException(); } #if SPAN_RUNTIME_SUPPORT this.span = MemoryMarshal.CreateSpan(ref array.DangerousGetReference(), array.GetLength(0)); #else this.Instance = array; this.Offset = ObjectMarshal.DangerousGetObjectDataByteOffset(array, ref array.DangerousGetReferenceAt(0, 0)); this.height = array.GetLength(0); #endif this.width = this.Stride = array.GetLength(1); }
/// <summary> /// Initializes a new instance of the <see cref="ReadOnlyMemory2D{T}"/> struct. /// </summary> /// <param name="text">The target <see cref="string"/> to wrap.</param> /// <param name="offset">The initial offset within <paramref name="text"/>.</param> /// <param name="height">The height of the resulting 2D area.</param> /// <param name="width">The width of each row in the resulting 2D area.</param> /// <param name="pitch">The pitch in the resulting 2D area.</param> /// <exception cref="ArgumentOutOfRangeException"> /// Thrown when one of the input parameters is out of range. /// </exception> /// <exception cref="ArgumentException"> /// Thrown when the requested area is outside of bounds for <paramref name="text"/>. /// </exception> public ReadOnlyMemory2D(string text, int offset, int height, int width, int pitch) { if ((uint)offset > (uint)text.Length) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForOffset(); } if (height < 0) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForHeight(); } if (width < 0) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForWidth(); } if (pitch < 0) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForPitch(); } int area = OverflowHelper.ComputeInt32Area(height, width, pitch), remaining = text.Length - offset; if (area > remaining) { ThrowHelper.ThrowArgumentException(); } this.instance = text; this.offset = ObjectMarshal.DangerousGetObjectDataByteOffset(text, ref text.DangerousGetReferenceAt(offset)); this.height = height; this.width = width; this.pitch = pitch; }
/// <summary> /// Initializes a new instance of the <see cref="ReadOnlyMemory2D{T}"/> struct wrapping a layer in a 3D array. /// </summary> /// <param name="array">The given 3D array to wrap.</param> /// <param name="depth">The target layer to map within <paramref name="array"/>.</param> /// <param name="row">The target row to map within <paramref name="array"/>.</param> /// <param name="column">The target column to map within <paramref name="array"/>.</param> /// <param name="height">The height to map within <paramref name="array"/>.</param> /// <param name="width">The width to map within <paramref name="array"/>.</param> /// <exception cref="ArgumentOutOfRangeException">Thrown when a parameter is invalid.</exception> public ReadOnlyMemory2D(T[,,] array, int depth, int row, int column, int height, int width) { if ((uint)depth >= (uint)array.GetLength(0)) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForDepth(); } int rows = array.GetLength(1), columns = array.GetLength(2); if ((uint)row >= (uint)rows) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForRow(); } if ((uint)column >= (uint)columns) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForColumn(); } if ((uint)height > (uint)(rows - row)) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForHeight(); } if ((uint)width > (uint)(columns - column)) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForWidth(); } this.instance = array; this.offset = ObjectMarshal.DangerousGetObjectDataByteOffset(array, ref array.DangerousGetReferenceAt(depth, row, column)); this.height = height; this.width = width; this.pitch = columns - width; }
private static IntPtr MeasureArray3DDataByteOffset() { var array = new T[1, 1, 1]; return(ObjectMarshal.DangerousGetObjectDataByteOffset(array, ref array[0, 0, 0])); }