Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.
/ corefx Public archive

Commit

Permalink
Add object null checks in Memory<T> APIs to support default (#14816)
Browse files Browse the repository at this point in the history
* Add object null checks in Memory<T> APIs to support default

* Changing Empty property to return default value.

* Update use of object null checks

* Addressing PR feedback.

* Removing typeof char check.

* Fix typo

Signed-off-by: dotnet-bot-corefx-mirror <dotnet-bot@microsoft.com>
  • Loading branch information
ahsonkhan authored and dotnet-bot committed Jan 13, 2018
1 parent 364bcc7 commit 995552e
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 37 deletions.
33 changes: 14 additions & 19 deletions src/Common/src/System.Private.CoreLib/shared/System/Memory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public readonly struct Memory<T>

// The highest order bit of _index is used to discern whether _object is an array/string or an owned memory
// if (_index >> 31) == 1, object _object is an OwnedMemory<T>
// else, object _object is a T[] or a string. It can only be a string if the Memory<T> was created by
// else, object _object is a T[] or a string. It can only be a string if the Memory<T> was created by
// using unsafe / marshaling code to reinterpret a ReadOnlyMemory<char> wrapped around a string as
// a Memory<T>.
private readonly object _object;
Expand Down Expand Up @@ -122,7 +122,7 @@ public static implicit operator ReadOnlyMemory<T>(Memory<T> memory) =>
/// <summary>
/// Returns an empty <see cref="Memory{T}"/>
/// </summary>
public static Memory<T> Empty { get; } = Array.Empty<T>();
public static Memory<T> Empty => default;

/// <summary>
/// The number of items in the memory.
Expand Down Expand Up @@ -187,15 +187,19 @@ public Span<T> Span
{
// This is dangerous, returning a writable span for a string that should be immutable.
// However, we need to handle the case where a ReadOnlyMemory<char> was created from a string
// and then cast to a Memory<T>. Such a cast can only be done with unsafe or marshaling code,
// and then cast to a Memory<T>. Such a cast can only be done with unsafe or marshaling code,
// in which case that's the dangerous operation performed by the dev, and we're just following
// suit here to make it work as best as possible.
return new Span<T>(ref Unsafe.As<char, T>(ref s.GetRawStringData()), s.Length).Slice(_index, _length);
}
else
else if (_object != null)
{
return new Span<T>((T[])_object, _index, _length);
}
else
{
return default;
}
}
}

Expand Down Expand Up @@ -224,7 +228,7 @@ public Span<T> Span

public unsafe MemoryHandle Retain(bool pin = false)
{
MemoryHandle memoryHandle;
MemoryHandle memoryHandle = default;
if (pin)
{
if (_index < 0)
Expand All @@ -243,9 +247,8 @@ public unsafe MemoryHandle Retain(bool pin = false)
void* pointer = Unsafe.Add<T>(Unsafe.AsPointer(ref s.GetRawStringData()), _index);
memoryHandle = new MemoryHandle(null, pointer, handle);
}
else
else if (_object is T[] array)
{
var array = (T[])_object;
var handle = GCHandle.Alloc(array, GCHandleType.Pinned);
void* pointer = Unsafe.Add<T>(Unsafe.AsPointer(ref array.GetRawSzArrayData()), _index);
memoryHandle = new MemoryHandle(null, pointer, handle);
Expand All @@ -258,10 +261,6 @@ public unsafe MemoryHandle Retain(bool pin = false)
((OwnedMemory<T>)_object).Retain();
memoryHandle = new MemoryHandle((OwnedMemory<T>)_object);
}
else
{
memoryHandle = new MemoryHandle(null);
}
}
return memoryHandle;
}
Expand All @@ -280,14 +279,10 @@ public bool TryGetArray(out ArraySegment<T> arraySegment)
return true;
}
}
else
else if (_object is T[] arr)
{
T[] arr = _object as T[];
if (typeof(T) != typeof(char) || arr != null)
{
arraySegment = new ArraySegment<T>(arr, _index, _length);
return true;
}
arraySegment = new ArraySegment<T>(arr, _index, _length);
return true;
}

arraySegment = default(ArraySegment<T>);
Expand Down Expand Up @@ -333,7 +328,7 @@ public bool Equals(Memory<T> other)
[EditorBrowsable(EditorBrowsableState.Never)]
public override int GetHashCode()
{
return CombineHashCodes(_object.GetHashCode(), _index.GetHashCode(), _length.GetHashCode());
return _object != null ? CombineHashCodes(_object.GetHashCode(), _index.GetHashCode(), _length.GetHashCode()) : 0;
}

private static int CombineHashCodes(int left, int right)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ public ReadOnlyMemory(T[] array, int start, int length)
_length = length;
}

/// <summary>Creates a new memory over the existing object, start, and length. No validation is performed.</summary>
/// <summary>Creates a new memory over the existing object, start, and length. No validation is performed.</summary>
/// <param name="obj">The target object.</param>
/// <param name="start">The index at which to begin the memory.</param>
/// <param name="length">The number of items in the memory.</param>
Expand Down Expand Up @@ -104,7 +104,7 @@ internal ReadOnlyMemory(object obj, int start, int length)
/// <summary>
/// Returns an empty <see cref="ReadOnlyMemory{T}"/>
/// </summary>
public static ReadOnlyMemory<T> Empty { get; } = Array.Empty<T>();
public static ReadOnlyMemory<T> Empty => default;

/// <summary>
/// The number of items in the memory.
Expand Down Expand Up @@ -169,10 +169,14 @@ public ReadOnlySpan<T> Span
{
return new ReadOnlySpan<T>(ref Unsafe.As<char, T>(ref s.GetRawStringData()), s.Length).Slice(_index, _length);
}
else
else if (_object != null)
{
return new ReadOnlySpan<T>((T[])_object, _index, _length);
}
else
{
return default;
}
}
}

Expand Down Expand Up @@ -206,7 +210,7 @@ public ReadOnlySpan<T> Span
/// </param>
public unsafe MemoryHandle Retain(bool pin = false)
{
MemoryHandle memoryHandle;
MemoryHandle memoryHandle = default;
if (pin)
{
if (_index < 0)
Expand All @@ -220,9 +224,8 @@ public unsafe MemoryHandle Retain(bool pin = false)
void* pointer = Unsafe.Add<T>(Unsafe.AsPointer(ref s.GetRawStringData()), _index);
memoryHandle = new MemoryHandle(null, pointer, handle);
}
else
else if (_object is T[] array)
{
var array = (T[])_object;
var handle = GCHandle.Alloc(array, GCHandleType.Pinned);
void* pointer = Unsafe.Add<T>(Unsafe.AsPointer(ref array.GetRawSzArrayData()), _index);
memoryHandle = new MemoryHandle(null, pointer, handle);
Expand All @@ -235,10 +238,6 @@ public unsafe MemoryHandle Retain(bool pin = false)
((OwnedMemory<T>)_object).Retain();
memoryHandle = new MemoryHandle((OwnedMemory<T>)_object);
}
else
{
memoryHandle = new MemoryHandle(null);
}
}
return memoryHandle;
}
Expand All @@ -258,14 +257,10 @@ public bool DangerousTryGetArray(out ArraySegment<T> arraySegment)
return true;
}
}
else
else if (_object is T[] arr)
{
T[] arr = _object as T[];
if (typeof(T) != typeof(char) || arr != null)
{
arraySegment = new ArraySegment<T>(arr, _index, _length);
return true;
}
arraySegment = new ArraySegment<T>(arr, _index, _length);
return true;
}

arraySegment = default;
Expand Down Expand Up @@ -313,7 +308,7 @@ public bool Equals(ReadOnlyMemory<T> other)
[EditorBrowsable(EditorBrowsableState.Never)]
public override int GetHashCode()
{
return CombineHashCodes(_object.GetHashCode(), _index.GetHashCode(), _length.GetHashCode());
return _object != null ? CombineHashCodes(_object.GetHashCode(), _index.GetHashCode(), _length.GetHashCode()) : 0;
}

private static int CombineHashCodes(int left, int right)
Expand Down

0 comments on commit 995552e

Please sign in to comment.