Adding missing ctor - 'public Span(T[] array, int start)' (#8354)
authorMatt Warren <matt.warren@live.co.uk>
Wed, 30 Nov 2016 07:45:21 +0000 (07:45 +0000)
committerJan Kotas <jkotas@microsoft.com>
Wed, 30 Nov 2016 07:45:21 +0000 (23:45 -0800)
src/mscorlib/model.xml
src/mscorlib/src/System/ReadOnlySpan.cs
src/mscorlib/src/System/Span.cs
tests/src/CoreMangLib/system/span/BasicSpanTest.cs

index 71c8cab22ec31d5a4292b68802794c0814ca6413..c338e5c0ef69a05b6753710fa5785ebaf5321710 100644 (file)
     </Type>
     <Type Name="System.Span&lt;T&gt;" 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&lt;T&gt;" />
     </Type>
     <Type Name="System.ReadOnlySpan&lt;T&gt;" 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&lt;T&gt;)" ReturnType="System.ReadOnlySpan&lt;T&gt;" />
index 4cdd14dfe4fe7fd58044d124b7d80d25793740c1..e94d3534fc3bb178077f17e092dea00de077daec 100644 (file)
@@ -36,6 +36,29 @@ namespace System
             _length = array.Length;
         }
 
+        /// <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 (&lt;0 or &gt;&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).
@@ -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 (&lt;0 or &gt;&eq;Length).
+        /// Thrown when the specified <paramref name="start"/> or end index is not in the range (&lt;0 or &gt;&eq;Length).
         /// </exception>
         public ReadOnlySpan(T[] array, int start, int length)
         {
index 64764ed2fd149941f26aff49172d96f3e77ab605..2eff6ae8006b22f0d2be8b70c158bfbc5264def6 100644 (file)
@@ -41,6 +41,34 @@ namespace System
             _length = array.Length;
         }
 
+        /// <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 (&lt;0 or &gt;=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).
@@ -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 (&lt;0 or &gt;&eq;Length).
+        /// Thrown when the specified <paramref name="start"/> or end index is not in the range (&lt;0 or &gt;=Length).
         /// </exception>
         public Span(T[] array, int start, int length)
         {
index 7b0be909c7b7c82ac268a2679281c705b7a99517..18ec6f8474ec07f7e4bbbeb2ce47a595c40e9fe7 100644 (file)
@@ -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