diff options
author | Matt Warren <matt.warren@live.co.uk> | 2016-11-30 07:45:21 +0000 |
---|---|---|
committer | Jan Kotas <jkotas@microsoft.com> | 2016-11-29 23:45:21 -0800 |
commit | fb5f8d70e8b85e084af2cb52b70914b3428652a1 (patch) | |
tree | 66fc375909ba2fed7ce93a23241170155a9c2f62 | |
parent | ce9a231f1498719eb665e2017611d7bfeb41ed49 (diff) | |
download | coreclr-fb5f8d70e8b85e084af2cb52b70914b3428652a1.tar.gz coreclr-fb5f8d70e8b85e084af2cb52b70914b3428652a1.tar.bz2 coreclr-fb5f8d70e8b85e084af2cb52b70914b3428652a1.zip |
Adding missing ctor - 'public Span(T[] array, int start)' (#8354)
-rw-r--r-- | src/mscorlib/model.xml | 2 | ||||
-rw-r--r-- | src/mscorlib/src/System/ReadOnlySpan.cs | 25 | ||||
-rw-r--r-- | src/mscorlib/src/System/Span.cs | 30 | ||||
-rw-r--r-- | tests/src/CoreMangLib/system/span/BasicSpanTest.cs | 129 |
4 files changed, 179 insertions, 7 deletions
diff --git a/src/mscorlib/model.xml b/src/mscorlib/model.xml index 71c8cab22e..c338e5c0ef 100644 --- a/src/mscorlib/model.xml +++ b/src/mscorlib/model.xml @@ -12397,6 +12397,7 @@ </Type> <Type Name="System.Span<T>" Condition="FEATURE_SPAN_OF_T"> <Member Name="#ctor(T[])" /> + <Member Name="#ctor(T[],System.Int32)" /> <Member Name="#ctor(T[],System.Int32,System.Int32)" /> <Member Name="#ctor(System.Void*,System.Int32)" /> <Member Name="op_Implicit(T[])" ReturnType="System.Span<T>" /> @@ -12415,6 +12416,7 @@ </Type> <Type Name="System.ReadOnlySpan<T>" Condition="FEATURE_SPAN_OF_T"> <Member Name="#ctor(T[])" /> + <Member Name="#ctor(T[],System.Int32)" /> <Member Name="#ctor(T[],System.Int32,System.Int32)" /> <Member Name="#ctor(System.Void*,System.Int32)" /> <Member Name="op_Implicit(System.Span<T>)" ReturnType="System.ReadOnlySpan<T>" /> diff --git a/src/mscorlib/src/System/ReadOnlySpan.cs b/src/mscorlib/src/System/ReadOnlySpan.cs index 4cdd14dfe4..e94d3534fc 100644 --- a/src/mscorlib/src/System/ReadOnlySpan.cs +++ b/src/mscorlib/src/System/ReadOnlySpan.cs @@ -38,6 +38,29 @@ namespace System /// <summary> /// Creates a new span over the portion of the target array beginning + /// at 'start' index and covering the remainder of the array. + /// </summary> + /// <param name="array">The target array.</param> + /// <param name="start">The index at which to begin the span.</param> + /// <exception cref="System.ArgumentNullException">Thrown when <paramref name="array"/> is a null + /// reference (Nothing in Visual Basic).</exception> + /// <exception cref="System.ArgumentOutOfRangeException"> + /// Thrown when the specified <paramref name="start"/> is not in the range (<0 or >&eq;Length). + /// </exception> + public ReadOnlySpan(T[] array, int start) + { + if (array == null) + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); + if ((uint)start > (uint)array.Length) + ThrowHelper.ThrowArgumentOutOfRangeException(); + + // TODO-SPAN: This has GC hole. It needs to be JIT intrinsic instead + _rawPointer = (IntPtr)Unsafe.AsPointer(ref Unsafe.Add(ref JitHelpers.GetArrayData(array), start)); + _length = array.Length - start; + } + + /// <summary> + /// Creates a new span over the portion of the target array beginning /// at 'start' index and ending at 'end' index (exclusive). /// </summary> /// <param name="array">The target array.</param> @@ -46,7 +69,7 @@ namespace System /// <exception cref="System.ArgumentNullException">Thrown when <paramref name="array"/> is a null /// reference (Nothing in Visual Basic).</exception> /// <exception cref="System.ArgumentOutOfRangeException"> - /// Thrown when the specified <paramref name="start"/> or end index is not in range (<0 or >&eq;Length). + /// Thrown when the specified <paramref name="start"/> or end index is not in the range (<0 or >&eq;Length). /// </exception> public ReadOnlySpan(T[] array, int start, int length) { diff --git a/src/mscorlib/src/System/Span.cs b/src/mscorlib/src/System/Span.cs index 64764ed2fd..2eff6ae800 100644 --- a/src/mscorlib/src/System/Span.cs +++ b/src/mscorlib/src/System/Span.cs @@ -43,6 +43,34 @@ namespace System /// <summary> /// Creates a new span over the portion of the target array beginning + /// at 'start' index and covering the remainder of the array. + /// </summary> + /// <param name="array">The target array.</param> + /// <param name="start">The index at which to begin the span.</param> + /// <exception cref="System.ArgumentNullException">Thrown when <paramref name="array"/> is a null + /// reference (Nothing in Visual Basic).</exception> + /// <exception cref="System.ArrayTypeMismatchException">Thrown when <paramref name="array"/> is covariant.</exception> + /// <exception cref="System.ArgumentOutOfRangeException"> + /// Thrown when the specified <paramref name="start"/> is not in the range (<0 or >=Length). + /// </exception> + public Span(T[] array, int start) + { + if (array == null) + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); + if (default(T) == null) { // Arrays of valuetypes are never covariant + if (array.GetType() != typeof(T[])) + ThrowHelper.ThrowArrayTypeMismatchException(); + } + if ((uint)start > (uint)array.Length) + ThrowHelper.ThrowArgumentOutOfRangeException(); + + // TODO-SPAN: This has GC hole. It needs to be JIT intrinsic instead + _rawPointer = (IntPtr)Unsafe.AsPointer(ref Unsafe.Add(ref JitHelpers.GetArrayData(array), start)); + _length = array.Length - start; + } + + /// <summary> + /// Creates a new span over the portion of the target array beginning /// at 'start' index and ending at 'end' index (exclusive). /// </summary> /// <param name="array">The target array.</param> @@ -52,7 +80,7 @@ namespace System /// reference (Nothing in Visual Basic).</exception> /// <exception cref="System.ArrayTypeMismatchException">Thrown when <paramref name="array"/> is covariant.</exception> /// <exception cref="System.ArgumentOutOfRangeException"> - /// Thrown when the specified <paramref name="start"/> or end index is not in range (<0 or >&eq;Length). + /// Thrown when the specified <paramref name="start"/> or end index is not in the range (<0 or >=Length). /// </exception> public Span(T[] array, int start, int length) { diff --git a/tests/src/CoreMangLib/system/span/BasicSpanTest.cs b/tests/src/CoreMangLib/system/span/BasicSpanTest.cs index 7b0be909c7..18ec6f8474 100644 --- a/tests/src/CoreMangLib/system/span/BasicSpanTest.cs +++ b/tests/src/CoreMangLib/system/span/BasicSpanTest.cs @@ -41,8 +41,11 @@ class My int failedTestsCount = 0; Test(CanAccessItemsViaIndexer, "CanAccessItemsViaIndexer", ref failedTestsCount); + Test(CanAccessItemsViaIndexerStartCtor, "CanAccessItemsViaIndexerStartCtor", ref failedTestsCount); + Test(CanAccessItemsViaIndexerStartLengthCtor, "CanAccessItemsViaIndexerStartLengthCtor", ref failedTestsCount); - Test(TestBoundaryEmptySpan, "TestBoundaryEmptySpan", ref failedTestsCount); + Test(TestBoundaryEmptySpanStartCtor, "TestBoundaryEmptySpanStartCtor", ref failedTestsCount); + Test(TestBoundaryEmptySpanStartLengthCtor, "TestBoundaryEmptySpanStartLengthCtor", ref failedTestsCount); Test(ReferenceTypesAreSupported, "ReferenceTypesAreSupported", ref failedTestsCount); @@ -51,6 +54,9 @@ class My Test(MustNotMoveGcTypesToUnmanagedMemory, "MustNotMoveGcTypesToUnmanagedMemory", ref failedTestsCount); Test(TestArrayCoVariance, "TestArrayCoVariance", ref failedTestsCount); + Test(TestArrayCoVarianceStartCtor, "TestArrayCoVarianceStartCtor", ref failedTestsCount); + Test(TestArrayCoVarianceStartLengthCtor, "TestArrayCoVarianceStartLengthCtor", ref failedTestsCount); + Test(TestArrayCoVarianceReadOnly, "TestArrayCoVarianceReadOnly", ref failedTestsCount); Test(CanCopyValueTypesWithoutPointersToSlice, "CanCopyValueTypesWithoutPointersToSlice", ref failedTestsCount); @@ -74,9 +80,13 @@ class My Test(SourceTypeLargerThanTargetOneCorrectlyCalcsTargetsLength, "SourceTypeLargerThanTargetOneCorrectlyCalcsTargetsLength", ref failedTestsCount); Test(WhenSourceDoesntFitIntoTargetLengthIsZero, "WhenSourceDoesntFitIntoTargetLengthIsZero", ref failedTestsCount); Test(WhenSourceFitsIntoTargetOnceLengthIsOne, "WhenSourceFitsIntoTargetOnceLengthIsOne", ref failedTestsCount); - Test(WhenSourceTypeLargerThaTargetAndOverflowsInt32ThrowsException, "WhenSourceTypeLargerThaTargetAndOverflowsInt32ThrowsException", ref failedTestsCount); + Test(WhenSourceTypeLargerThanTargetAndOverflowsInt32ThrowsException, "WhenSourceTypeLargerThanTargetAndOverflowsInt32ThrowsException", ref failedTestsCount); Test(CanCreateSpanFromString, "CanCreateSpanFromString", ref failedTestsCount); + Test(WhenStartLargerThanLengthThrowsExceptionStartCtor, "WhenStartLargerThanLengthThrowsExceptionStartCtor", ref failedTestsCount); + Test(WhenStartLargerThanLengthThrowsExceptionStartLengthCtor, "WhenStartLargerThanLengthThrowsExceptionStartLengthCtor", ref failedTestsCount); + Test(WhenStartAndLengthLargerThanLengthThrowsExceptionStartLengthCtor, "WhenStartAndLengthLargerThanLengthThrowsExceptionStartLengthCtor", ref failedTestsCount); + Console.WriteLine(string.Format("{0} tests has failed", failedTestsCount)); Environment.Exit(failedTestsCount); } @@ -91,9 +101,31 @@ class My AssertTrue(Sum(subslice) == 5, "Failed to sum subslice"); } - static TestBoundaryEmptySpan() + static void CanAccessItemsViaIndexerStartCtor() + { + int[] a = new int[] { 1, 2, 3 }; + Span<int> slice = new Span<int>(a, start: 1); + AssertTrue(Sum(slice) == 5, "Failed to sum slice"); + } + + static void CanAccessItemsViaIndexerStartLengthCtor() + { + int[] a = new int[] { 1, 2, 3 }; + Span<int> slice = new Span<int>(a, start: 1, length: 1); + AssertTrue(Sum(slice) == 2, "Failed to sum slice"); + } + + static void TestBoundaryEmptySpanStartCtor() { - int[] a = new byte[5]; + int[] a = new int[5]; + + Span<int> slice = new Span<int>(a, start: a.Length); + AssertEqual(slice.Length, 0); + } + + static void TestBoundaryEmptySpanStartLengthCtor() + { + int[] a = new int[5]; Span<int> slice = new Span<int>(a, a.Length, 0); AssertEqual(slice.Length, 0); @@ -165,6 +197,54 @@ class My } } + static void TestArrayCoVarianceStartCtor() + { + var array = new ReferenceType[1]; + var objArray = (object[])array; + try + { + new Span<object>(objArray, start: 0); + AssertTrue(false, "Expected exception not thrown"); + } + catch (ArrayTypeMismatchException) + { + } + + var objEmptyArray = Array.Empty<ReferenceType>(); + try + { + new Span<object>(objEmptyArray, start: 0); + AssertTrue(false, "Expected exception not thrown"); + } + catch (ArrayTypeMismatchException) + { + } + } + + static void TestArrayCoVarianceStartLengthCtor() + { + var array = new ReferenceType[1]; + var objArray = (object[])array; + try + { + new Span<object>(objArray, start: 0, length: 1); + AssertTrue(false, "Expected exception not thrown"); + } + catch (ArrayTypeMismatchException) + { + } + + var objEmptyArray = Array.Empty<ReferenceType>(); + try + { + new Span<object>(objEmptyArray, start: 0, length: 1); + AssertTrue(false, "Expected exception not thrown"); + } + catch (ArrayTypeMismatchException) + { + } + } + static void TestArrayCoVarianceReadOnly() { var array = new ReferenceType[1]; @@ -603,7 +683,7 @@ class My } } - static void WhenSourceTypeLargerThaTargetAndOverflowsInt32ThrowsException() + static void WhenSourceTypeLargerThanTargetAndOverflowsInt32ThrowsException() { unsafe { @@ -637,6 +717,45 @@ class My AssertEqualContent(secondHalfOfString, spanFromSecondHalf); } + static void WhenStartLargerThanLengthThrowsExceptionStartCtor() + { + try + { + var data = new byte[10]; + var slice = new Span<byte>(data, start: 11); + AssertTrue(false, "Expected exception for Argument Out of Range not thrown"); + } + catch (System.ArgumentOutOfRangeException) + { + } + } + + static void WhenStartLargerThanLengthThrowsExceptionStartLengthCtor() + { + try + { + var data = new byte[10]; + var slice = new Span<byte>(data, start: 11, length: 0); + AssertTrue(false, "Expected exception for Argument Out of Range not thrown"); + } + catch (System.ArgumentOutOfRangeException) + { + } + } + + static void WhenStartAndLengthLargerThanLengthThrowsExceptionStartLengthCtor() + { + try + { + var data = new byte[10]; + var slice = new Span<byte>(data, start: 1, length: 10); + AssertTrue(false, "Expected exception for Argument Out of Range not thrown"); + } + catch (System.ArgumentOutOfRangeException) + { + } + } + static void Test(Action test, string testName, ref int failedTestsCount) { try |