From: James Ko Date: Mon, 10 Apr 2017 17:26:12 +0000 (-0400) Subject: Implement slicing APIs for ArraySegment (#9926) X-Git-Tag: accepted/tizen/base/20180629.140029~1492 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=40ecbb723552407044b57edaf3e5a1408bf99aab;p=platform%2Fupstream%2Fcoreclr.git Implement slicing APIs for ArraySegment (#9926) --- diff --git a/src/mscorlib/src/System/ArraySegment.cs b/src/mscorlib/src/System/ArraySegment.cs index e0118c2..a18590d 100644 --- a/src/mscorlib/src/System/ArraySegment.cs +++ b/src/mscorlib/src/System/ArraySegment.cs @@ -28,6 +28,10 @@ namespace System [Serializable] public struct ArraySegment : IList, IReadOnlyList { + // Do not replace the array allocation with Array.Empty. We don't want to have the overhead of + // instantiating another generic type in addition to ArraySegment for new type parameters. + public static ArraySegment Empty { get; } = new ArraySegment(new T[0]); + private readonly T[] _array; private readonly int _offset; private readonly int _count; @@ -63,12 +67,31 @@ namespace System public int Count => _count; - public Enumerator GetEnumerator() + public T this[int index] { - if (_array == null) - ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_NullArray); - Contract.EndContractBlock(); + get + { + if ((uint)index >= (uint)_count) + { + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index); + } + return _array[_offset + index]; + } + set + { + if ((uint)index >= (uint)_count) + { + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index); + } + + _array[_offset + index] = value; + } + } + + public Enumerator GetEnumerator() + { + ThrowInvalidOperationIfDefault(); return new Enumerator(this); } @@ -89,6 +112,27 @@ namespace System return hash; } + public void CopyTo(T[] destination) => CopyTo(destination, 0); + + public void CopyTo(T[] destination, int destinationIndex) + { + ThrowInvalidOperationIfDefault(); + System.Array.Copy(_array, _offset, destination, destinationIndex, _count); + } + + public void CopyTo(ArraySegment destination) + { + ThrowInvalidOperationIfDefault(); + destination.ThrowInvalidOperationIfDefault(); + + if (_count > destination._count) + { + ThrowHelper.ThrowArgumentException_DestinationTooShort(); + } + + System.Array.Copy(_array, _offset, destination._array, destination._offset, _count); + } + public override bool Equals(Object obj) { if (obj is ArraySegment) @@ -102,6 +146,44 @@ namespace System return obj._array == _array && obj._offset == _offset && obj._count == _count; } + public ArraySegment Slice(int index) + { + ThrowInvalidOperationIfDefault(); + + if ((uint)index > (uint)_count) + { + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index); + } + + return new ArraySegment(_array, _offset + index, _count - index); + } + + public ArraySegment Slice(int index, int count) + { + ThrowInvalidOperationIfDefault(); + + if ((uint)index > (uint)_count || (uint)count > (uint)(_count - index)) + { + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index); + } + + return new ArraySegment(_array, _offset + index, count); + } + + public T[] ToArray() + { + ThrowInvalidOperationIfDefault(); + + if (_count == 0) + { + return Empty._array; + } + + var array = new T[_count]; + System.Array.Copy(_array, _offset, array, 0, _count); + return array; + } + public static bool operator ==(ArraySegment a, ArraySegment b) { return a.Equals(b); @@ -112,13 +194,14 @@ namespace System return !(a == b); } + public static implicit operator ArraySegment(T[] array) => new ArraySegment(array); + #region IList T IList.this[int index] { get { - if (_array == null) - ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_NullArray); + ThrowInvalidOperationIfDefault(); if (index < 0 || index >= _count) ThrowHelper.ThrowArgumentOutOfRange_IndexException(); Contract.EndContractBlock(); @@ -128,8 +211,7 @@ namespace System set { - if (_array == null) - ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_NullArray); + ThrowInvalidOperationIfDefault(); if (index < 0 || index >= _count) ThrowHelper.ThrowArgumentOutOfRange_IndexException(); Contract.EndContractBlock(); @@ -140,9 +222,7 @@ namespace System int IList.IndexOf(T item) { - if (_array == null) - ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_NullArray); - Contract.EndContractBlock(); + ThrowInvalidOperationIfDefault(); int index = System.Array.IndexOf(_array, item, _offset, _count); @@ -168,8 +248,7 @@ namespace System { get { - if (_array == null) - ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_NullArray); + ThrowInvalidOperationIfDefault(); if (index < 0 || index >= _count) ThrowHelper.ThrowArgumentOutOfRange_IndexException(); Contract.EndContractBlock(); @@ -202,9 +281,7 @@ namespace System bool ICollection.Contains(T item) { - if (_array == null) - ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_NullArray); - Contract.EndContractBlock(); + ThrowInvalidOperationIfDefault(); int index = System.Array.IndexOf(_array, item, _offset, _count); @@ -214,15 +291,6 @@ namespace System return index >= 0; } - void ICollection.CopyTo(T[] array, int arrayIndex) - { - if (_array == null) - ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_NullArray); - Contract.EndContractBlock(); - - System.Array.Copy(_array, _offset, array, arrayIndex, _count); - } - bool ICollection.Remove(T item) { ThrowHelper.ThrowNotSupportedException(); @@ -240,6 +308,14 @@ namespace System IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); #endregion + private void ThrowInvalidOperationIfDefault() + { + if (_array == null) + { + ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_NullArray); + } + } + [Serializable] public struct Enumerator : IEnumerator {