<Compile Include="$(MSBuildThisFileDirectory)System\IEquatable.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\IFormatProvider.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\IFormattable.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Index.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\IndexOutOfRangeException.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\InsufficientExecutionStackException.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\InsufficientMemoryException.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\PlatformNotSupportedException.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Progress.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Random.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Range.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\RankException.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\ReadOnlySpan.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\ReadOnlySpan.Fast.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\SemaphoreFullException.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\SemaphoreSlim.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\SendOrPostCallback.cs" />
- <Compile Include="$(MSBuildThisFileDirectory)System\Threading\SpinLock.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Threading\SpinLock.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\SpinWait.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\SynchronizationLockException.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\ThreadLocal.cs" />
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System
+{
+ public readonly struct Index : IEquatable<Index>
+ {
+ private readonly int _value;
+
+ public Index(int value, bool fromEnd)
+ {
+ if (value < 0)
+ {
+ ThrowHelper.ThrowValueArgumentOutOfRange_NeedNonNegNumException();
+ }
+
+ _value = fromEnd ? ~value : value;
+ }
+
+ public int Value => _value < 0 ? ~_value : _value;
+ public bool FromEnd => _value < 0;
+ public override bool Equals(object value) => value is Index && _value == ((Index)value)._value;
+ public bool Equals (Index other) => _value == other._value;
+
+ public override int GetHashCode()
+ {
+ return _value;
+ }
+
+ public override string ToString()
+ {
+ string str = Value.ToString();
+ return FromEnd ? "^" + str : str;
+ }
+
+ public static implicit operator Index(int value)
+ => new Index(value, fromEnd: false);
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System
+{
+ public readonly struct Range : IEquatable<Range>
+ {
+ public Index Start { get; }
+ public Index End { get; }
+
+ private Range(Index start, Index end)
+ {
+ Start = start;
+ End = end;
+ }
+
+ public override bool Equals(object value)
+ {
+ if (value is Range)
+ {
+ Range r = (Range)value;
+ return r.Start.Equals(Start) && r.End.Equals(End);
+ }
+
+ return false;
+ }
+
+ public bool Equals (Range other) => other.Start.Equals(Start) && other.End.Equals(End);
+
+ public override int GetHashCode()
+ {
+ return HashCode.Combine(Start.GetHashCode(), End.GetHashCode());
+ }
+
+ public override string ToString()
+ {
+ return Start + ".." + End;
+ }
+
+ public static Range Create(Index start, Index end) => new Range(start, end);
+ public static Range FromStart(Index start) => new Range(start, new Index(0, fromEnd: true));
+ public static Range ToEnd(Index end) => new Range(new Index(0, fromEnd: false), end);
+ public static Range All() => new Range(new Index(0, fromEnd: false), new Index(0, fromEnd: true));
+ }
+}
#endif
}
+ public ref readonly T this[Index index]
+ {
+ get
+ {
+ return ref this [index.FromEnd ? _length - index.Value : index.Value];
+ }
+ }
+
+ public ReadOnlySpan<T> this[Range range]
+ {
+ get
+ {
+ int start = range.Start.FromEnd ? _length - range.Start.Value : range.Start.Value;
+ int end = range.End.FromEnd ? _length - range.End.Value : range.End.Value;
+ return Slice(start, end - start);
+ }
+ }
+
/// <summary>
/// Returns a reference to the 0th element of the Span. If the Span is empty, returns null reference.
/// It can be used for pinning and is required to support the use of span within a fixed statement.
#endif
}
+ public ref T this[Index index]
+ {
+ get
+ {
+ return ref this [index.FromEnd ? _length - index.Value : index.Value];
+ }
+ }
+
+ public Span<T> this[Range range]
+ {
+ get
+ {
+ int start = range.Start.FromEnd ? _length - range.Start.Value : range.Start.Value;
+ int end = range.End.FromEnd ? _length - range.End.Value : range.End.Value;
+ return Slice(start, end - start);
+ }
+ }
+
/// <summary>
/// Returns a reference to the 0th element of the Span. If the Span is empty, returns null reference.
/// It can be used for pinning and is required to support the use of span within a fixed statement.
// This file defines an internal class used to throw exceptions in BCL code.
-// The main purpose is to reduce code size.
-//
+// The main purpose is to reduce code size.
+//
// The old way to throw an exception generates quite a lot IL code and assembly code.
// Following is an example:
// C# source
// IL_0012: newobj instance void System.ArgumentNullException::.ctor(string,string)
// IL_0017: throw
// which is 21bytes in IL.
-//
+//
// So we want to get rid of the ldstr and call to Environment.GetResource in IL.
// In order to do that, I created two enums: ExceptionResource, ExceptionArgument to represent the
-// argument name and resource name in a small integer. The source code will be changed to
+// argument name and resource name in a small integer. The source code will be changed to
// ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key, ExceptionResource.ArgumentNull_Key);
//
// The IL code will be 7 bytes.
// IL_000a: call void System.ThrowHelper::ThrowArgumentNullException(valuetype System.ExceptionArgument)
// IL_000f: ldarg.0
//
-// This will also reduce the Jitted code size a lot.
+// This will also reduce the Jitted code size a lot.
+//
+// It is very important we do this for generic classes because we can easily generate the same code
+// multiple times for different instantiation.
//
-// It is very important we do this for generic classes because we can easily generate the same code
-// multiple times for different instantiation.
-//
using System.Collections.Generic;
using System.Diagnostics;
ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
}
+ internal static void ThrowValueArgumentOutOfRange_NeedNonNegNumException()
+ {
+ throw GetArgumentOutOfRangeException(ExceptionArgument.value,
+ ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
+ }
+
internal static void ThrowLengthArgumentOutOfRange_ArgumentOutOfRange_NeedNonNegNum()
{
throw GetArgumentOutOfRangeException(ExceptionArgument.length,