summaryrefslogtreecommitdiff
path: root/src/mscorlib/src/System/ArraySegment.cs
diff options
context:
space:
mode:
authorJiyoung Yun <jy910.yun@samsung.com>2017-04-13 14:17:19 +0900
committerJiyoung Yun <jy910.yun@samsung.com>2017-04-13 14:17:19 +0900
commita56e30c8d33048216567753d9d3fefc2152af8ac (patch)
tree7e5d979695fc4a431740982eb1cfecc2898b23a5 /src/mscorlib/src/System/ArraySegment.cs
parent4b11dc566a5bbfa1378d6266525c281b028abcc8 (diff)
downloadcoreclr-a56e30c8d33048216567753d9d3fefc2152af8ac.tar.gz
coreclr-a56e30c8d33048216567753d9d3fefc2152af8ac.tar.bz2
coreclr-a56e30c8d33048216567753d9d3fefc2152af8ac.zip
Imported Upstream version 2.0.0.11353upstream/2.0.0.11353
Diffstat (limited to 'src/mscorlib/src/System/ArraySegment.cs')
-rw-r--r--src/mscorlib/src/System/ArraySegment.cs178
1 files changed, 106 insertions, 72 deletions
diff --git a/src/mscorlib/src/System/ArraySegment.cs b/src/mscorlib/src/System/ArraySegment.cs
index 03556e492a..a18590d5d8 100644
--- a/src/mscorlib/src/System/ArraySegment.cs
+++ b/src/mscorlib/src/System/ArraySegment.cs
@@ -15,6 +15,7 @@
using System.Collections;
using System.Collections.Generic;
+using System.Diagnostics;
using System.Diagnostics.Contracts;
namespace System
@@ -27,6 +28,10 @@ namespace System
[Serializable]
public struct ArraySegment<T> : IList<T>, IReadOnlyList<T>
{
+ // 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<T> for new type parameters.
+ public static ArraySegment<T> Empty { get; } = new ArraySegment<T>(new T[0]);
+
private readonly T[] _array;
private readonly int _offset;
private readonly int _count;
@@ -45,8 +50,9 @@ namespace System
public ArraySegment(T[] array, int offset, int count)
{
// Validate arguments, check is minimal instructions with reduced branching for inlinable fast-path
+ // Negative values discovered though conversion to high values when converted to unsigned
// Failure should be rare and location determination and message is delegated to failure functions
- if (array == null || (offset | count) < 0 || (array.Length - offset < count))
+ if (array == null || (uint)offset > (uint)array.Length || (uint)count > (uint)(array.Length - offset))
ThrowHelper.ThrowArraySegmentCtorValidationFailedExceptions(array, offset, count);
Contract.EndContractBlock();
@@ -55,62 +61,37 @@ namespace System
_count = count;
}
- public T[] Array
- {
- get
- {
- Debug.Assert( (null == _array && 0 == _offset && 0 == _count)
- || (null != _array && _offset >= 0 && _count >= 0 && _offset + _count <= _array.Length),
- "ArraySegment is invalid");
+ public T[] Array => _array;
- return _array;
- }
- }
+ public int Offset => _offset;
- public int Offset
+ public int Count => _count;
+
+ public T this[int index]
{
get
{
- // Since copying value types is not atomic & callers cannot atomically
- // read all three fields, we cannot guarantee that Offset is within
- // the bounds of Array. That is our intent, but let's not specify
- // it as a postcondition - force callers to re-verify this themselves
- // after reading each field out of an ArraySegment into their stack.
- Contract.Ensures(Contract.Result<int>() >= 0);
-
- Debug.Assert( (null == _array && 0 == _offset && 0 == _count)
- || (null != _array && _offset >= 0 && _count >= 0 && _offset + _count <= _array.Length),
- "ArraySegment is invalid");
-
- return _offset;
- }
- }
+ if ((uint)index >= (uint)_count)
+ {
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index);
+ }
- public int Count
- {
- get
+ return _array[_offset + index];
+ }
+ set
{
- // Since copying value types is not atomic & callers cannot atomically
- // read all three fields, we cannot guarantee that Count is within
- // the bounds of Array. That's our intent, but let's not specify
- // it as a postcondition - force callers to re-verify this themselves
- // after reading each field out of an ArraySegment into their stack.
- Contract.Ensures(Contract.Result<int>() >= 0);
-
- Debug.Assert( (null == _array && 0 == _offset && 0 == _count)
- || (null != _array && _offset >= 0 && _count >= 0 && _offset + _count <= _array.Length),
- "ArraySegment is invalid");
-
- return _count;
+ if ((uint)index >= (uint)_count)
+ {
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index);
+ }
+
+ _array[_offset + index] = value;
}
}
public Enumerator GetEnumerator()
{
- if (_array == null)
- ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_NullArray);
- Contract.EndContractBlock();
-
+ ThrowInvalidOperationIfDefault();
return new Enumerator(this);
}
@@ -120,17 +101,38 @@ namespace System
{
return 0;
}
-
+
int hash = 5381;
hash = System.Numerics.Hashing.HashHelpers.Combine(hash, _offset);
hash = System.Numerics.Hashing.HashHelpers.Combine(hash, _count);
-
+
// The array hash is expected to be an evenly-distributed mixture of bits,
// so rather than adding the cost of another rotation we just xor it.
hash ^= _array.GetHashCode();
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<T> 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<T>)
@@ -138,30 +140,69 @@ namespace System
else
return false;
}
-
+
public bool Equals(ArraySegment<T> obj)
{
return obj._array == _array && obj._offset == _offset && obj._count == _count;
}
-
+
+ public ArraySegment<T> Slice(int index)
+ {
+ ThrowInvalidOperationIfDefault();
+
+ if ((uint)index > (uint)_count)
+ {
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index);
+ }
+
+ return new ArraySegment<T>(_array, _offset + index, _count - index);
+ }
+
+ public ArraySegment<T> Slice(int index, int count)
+ {
+ ThrowInvalidOperationIfDefault();
+
+ if ((uint)index > (uint)_count || (uint)count > (uint)(_count - index))
+ {
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index);
+ }
+
+ return new ArraySegment<T>(_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<T> a, ArraySegment<T> b)
{
return a.Equals(b);
}
-
+
public static bool operator !=(ArraySegment<T> a, ArraySegment<T> b)
{
return !(a == b);
}
+ public static implicit operator ArraySegment<T>(T[] array) => new ArraySegment<T>(array);
+
#region IList<T>
T IList<T>.this[int index]
{
get
{
- if (_array == null)
- ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_NullArray);
- if (index < 0 || index >= _count)
+ ThrowInvalidOperationIfDefault();
+ if (index < 0 || index >= _count)
ThrowHelper.ThrowArgumentOutOfRange_IndexException();
Contract.EndContractBlock();
@@ -170,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();
@@ -182,9 +222,7 @@ namespace System
int IList<T>.IndexOf(T item)
{
- if (_array == null)
- ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_NullArray);
- Contract.EndContractBlock();
+ ThrowInvalidOperationIfDefault();
int index = System.Array.IndexOf<T>(_array, item, _offset, _count);
@@ -210,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();
@@ -244,9 +281,7 @@ namespace System
bool ICollection<T>.Contains(T item)
{
- if (_array == null)
- ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_NullArray);
- Contract.EndContractBlock();
+ ThrowInvalidOperationIfDefault();
int index = System.Array.IndexOf<T>(_array, item, _offset, _count);
@@ -256,15 +291,6 @@ namespace System
return index >= 0;
}
- void ICollection<T>.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<T>.Remove(T item)
{
ThrowHelper.ThrowNotSupportedException();
@@ -282,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<T>
{